OpenRouter
OpenRouter
OpenRouter은 하나의 API로 여러 프로바이더의 모델에 접근하게 해 주는 게이트웨이예요. Confident AI는 Python·TypeScript용 OpenTelemetry 네이티브 추적 SDK인 confident-trace로 OpenRouter 호출을 추적·평가합니다.
출처: 문서
본문
개요
OpenRouter은 하나의 API로 여러 프로바이더의 모델에 접근하게 해 주는 게이트웨이입니다. Confident AI는 Python·TypeScript용 OpenTelemetry 네이티브 추적 SDK인 confident-trace로 OpenRouter 호출을 추적·평가해요.
이 통합은 지원되는 호출에서 다음 데이터를 포착합니다.
- LLM 스팬 — 모델 이름, 타이밍, 상태, 토큰 사용량
- 메시지 — 입출력 메시지와 모델이 반환한 도구 호출 데이터
- 스트리밍 출력 — 애플리케이션이 소비하는 대로의 응답 콘텐츠
OpenRouter의 호스팅 런타임은 애플리케이션과 분리되어 있어요. 게이트웨이 측 트레이스로는 Broadcast → OpenTelemetry Collector가 OTLP/HTTP JSON 목적지를 지원합니다. Settings → Observability에서 Broadcast를 켜고
{"x-confident-api-key": "<your-confident-project-key>"}헤더와 함께https://otel.confident-ai.com/v1/traces를 구성하세요. EU면https://eu.otel.confident-ai.com/v1/traces, 자체 호스팅이면 내 Confident 트레이스 엔드포인트를 쓰세요. 저장 전에 연결을 테스트하세요. Broadcast는 게이트웨이 활동을 기록하고, 아래 SDK 예제는 애플리케이션 안의 호출을 기록해요.
| Runtime | Requirements | Setup |
|---|---|---|
| Python | Python 3.10+, openrouter >=1.1.136 <1.2 |
Call init() before model calls |
| TypeScript | Node.js 22+, @openrouter/sdk >=1.2.116 <1.3 |
Call init() and launch with the register preload |
이 예제들은 위 네이티브 SDK 버전을 대상으로 합니다. TypeScript는 지원되는 SDK 범위가 요구하는 chatRequest 래퍼를 사용해요.
자동 계측
의존성 설치
confident-trace를 예제에서 쓰는 클라이언트와 함께 설치하세요.
Python
pip install confident-trace
TypeScript
tsx는 TypeScript 소스를 직접 실행할 때만 필요해요.
npm install confident-trace
npm install -D tsx
yarn add confident-trace
yarn add -D tsx
API 키 설정
Confident AI에서 프로젝트 API 키를 받아 모델 클라이언트 자격 증명을 설정하세요.
export CONFIDENT_API_KEY="<your-confident-project-key>"
export OPENROUTER_API_KEY="<your-gateway-key>"
EU 프로젝트라면
CONFIDENT_OTEL_ENDPOINT="https://eu.otel.confident-ai.com/v1/traces"를 설정하세요. 자체 호스팅 배포라면 전체 OTLP/HTTP 트레이스 URL을 사용하세요. US 프로젝트는 기본적으로https://otel.confident-ai.com/v1/traces를 사용해요. 이 설정은 트레이스 export를 제어하고, 게이트웨이 base URL은 모델 요청을 제어합니다.
OpenRouter 계측
모델 호출을 하기 전에 init()을 한 번 호출하세요. 설치된 네이티브 SDK를 계측해 주며, 클라이언트는 평소처럼 쓰면 돼요.
Python
import os
from confident_trace import init, shutdown
from openrouter import OpenRouter
init()
client = OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"])
try:
response = client.chat.send(
model="openai/gpt-4o-mini",
messages=[
{"role": "user", "content": "Explain OpenTelemetry in one sentence."}
],
)
print(response.choices[0].message.content)
finally:
shutdown()
TypeScript
import { OpenRouter } from "@openrouter/sdk";
import { init } from "confident-trace";
const runtime = init();
const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY! });
try {
const response = await client.chat.send({
chatRequest: {
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "Explain OpenTelemetry in one sentence." }],
},
});
console.log(response);
} finally {
await runtime.shutdown();
}
장기 실행 서버에서는 시작 시
init()을 한 번, 정상 종료 시 활성 요청이 끝난 뒤shutdown()을 한 번 호출하세요 — 요청마다 하지 마세요. flush와 shutdown을 참고하세요.
OpenRouter 실행
Python
python main.py
TypeScript
Node가 SDK를 로드할 때 훅할 수 있도록 엔트리포인트를 confident-trace/register preload로 실행하세요. 자동 추적에는 preload와 init() 둘 다 필요해요.
# Running TypeScript source directly
node --import tsx --import confident-trace/register src/index.ts
# Running compiled JavaScript
node --import confident-trace/register dist/index.js
완료 ✅. Confident AI 프로젝트에서 Observatory를 열어 트레이스와 모델 호출 스팬을 확인하세요.
OpenAI 호환 클라이언트
이미 OpenAI SDK를 쓰고 있다면 그대로 두고 클라이언트를 게이트웨이로 가리키세요. confident-trace와 함께 Python용 openai>=1.109,<4 또는 TypeScript용 openai>=7.10.0 <8을 설치하세요.
아래 공용 엔드포인트는 자동 감지됩니다. 커스텀 엔드포인트라면 openrouter_proxy_urls / openrouterProxyUrls로 정확한 URL도 등록하세요.
Python
import os
from openai import OpenAI
from confident_trace import init
base_url = "https://openrouter.ai/api/v1"
init()
client = OpenAI(base_url=base_url, api_key=os.environ["OPENROUTER_API_KEY"])
TypeScript
import OpenAI from "openai";
import { init } from "confident-trace";
const baseURL = "https://openrouter.ai/api/v1";
const runtime = init();
const client = new OpenAI({ baseURL, apiKey: process.env.OPENROUTER_API_KEY! });
이 설정 조각들은 빠른 시작의 클라이언트 설정을 대체하고, 그 shutdown 처리는 유지합니다. client.chat.completions.create(...) 또는 client.responses.create(...)를 사용하세요(스트리밍 포함). 게이트웨이 라우팅은 여전히 유효한 모델 이름과 자격 증명에 달려 있어요. 매칭은 끝의 슬래시를 무시하지만 스킴, 호스트, 포트, 전체 base path는 포함합니다.
수동 TypeScript 설정이라면, 네이티브 클라이언트로 confident-trace/openrouter의 instrumentOpenRouter(client)로 export를 초기화하거나, OpenAI 클라이언트로 confident-trace/openai의 instrumentOpenAI(client)를 사용하세요. 수동 어댑터는 preload가 필요 없어요.
무엇이 포착되나
지원되는 각 애플리케이션 호출은 모델 호출 스팬을 만듭니다. 활성 스팬 아래에 중첩되고, 부모가 없으면 새 트레이스를 시작해요.
- 지원 API — 두 언어 모두 네이티브
chat.send, Python의chat.send_async(스트리밍 포함). 네이티브 Responses, 임베딩, Agent SDK, 기능 SDK 헬퍼는 이 통합 범위 밖입니다. - 모델·사용량 — 요청된 모델이나 별칭, 가능할 때 반환된 모델, 응답 ID, 완료 사유, 게이트웨이가 제공한 토큰 수
- 메시지·도구 — 정규화된 입출력 메시지와 도구 호출 데이터. 도구 실행은 별도 작업이며 이 게이트웨이 통합으로 추적되지 않아요.
- 게이트웨이 아이덴티티 — 네이티브 SDK 스팬은
OpenRouter통합 라벨을 사용합니다. OpenAI 프록시 스팬은OpenAI를 유지하고confident.gateway.name=openrouter를 추가해요. 둘 다 프로바이더 이름openrouter를 기록합니다.
메시지는 콘텐츠 정책을 따릅니다(포착 거부, 삭제, 구성된 크기 제한 포함). 이진 다중모달 페이로드는 제외돼요.
애플리케이션 스팬은 내 코드가 만드는 호출을 나타냅니다. 게이트웨이 내부의 모든 재시도·폴백·라우팅 결정을 드러내지는 않아요. 게이트웨이 export에는 자체 스팬 속성과 콘텐츠 설정이 있습니다. 두 경로를 모두 켜면 클라이언트·게이트웨이 스팬이 모두 보일 수 있어요. 그것들을 하나의 분산 트레이스로 연결하려면 모델 이름 매칭이 아니라 컨텍스트 전파가 필요합니다.
스트리밍
스트리밍도 같은 설정을 사용합니다. 각 예제에는 초기화와 종료가 포함돼요.
Python
import os
from confident_trace import init, shutdown
from openrouter import OpenRouter
init()
client = OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"])
try:
stream = client.chat.send(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Tell me a short story."}],
stream=True,
)
try:
for chunk in stream:
print(chunk)
finally:
stream.close()
finally:
shutdown()
TypeScript
import { OpenRouter } from "@openrouter/sdk";
import { init } from "confident-trace";
const runtime = init();
const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY! });
try {
const stream = await client.chat.send({
chatRequest: {
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "Tell me a short story." }],
stream: true,
},
});
if (!(Symbol.asyncIterator in stream)) {
throw new Error("Expected a streaming response");
}
for await (const chunk of stream) {
console.log(chunk);
}
} finally {
await runtime.shutdown();
}
Python 비동기 코드에서는 await client.chat.send_async(...)을 쓰고, async for로 스트림을 소비하세요. TypeScript 네이티브 SDK는 ESM입니다. CommonJS 애플리케이션은 동적 import()로 로드할 수 있어요.
shutdown()전에 스트림을 소비하거나 닫으세요. TypeScript에서는 스트림을 소비하거나 클라이언트 SDK의 취소 제어를 사용하세요. 버려진 스트림은 스팬을 불완전하게 남길 수 있어요. flush와 shutdown을 참고하세요.
트레이스 스팬 속성 설정
호출이 시작되기 전에 아는 속성을 추가하려면 트레이스 컨텍스트를 사용하세요. 추가 스팬은 만들지 않아요. 각 예제는 호출 전에 추적을 초기화하고 클라이언트를 만듭니다.
Python
import os
from confident_trace import init, shutdown, trace_context
from openrouter import OpenRouter
init()
client = OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"])
try:
with trace_context(
tags=["support"],
metadata={"gateway": "openrouter"},
user_id="user-42",
customer_id="customer-7",
):
response = client.chat.send(
model="openai/gpt-4o-mini",
messages=[
{"role": "user", "content": "Explain OpenTelemetry in one sentence."}
],
)
finally:
shutdown()
TypeScript
import { OpenRouter } from "@openrouter/sdk";
import { init, traceContext } from "confident-trace";
const runtime = init();
const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY! });
try {
const response = await traceContext(
{
tags: ["support"],
metadata: { gateway: "openrouter" },
userId: "user-42",
customerId: "customer-7",
},
() =>
client.chat.send({
chatRequest: {
model: "openai/gpt-4o-mini",
messages: [
{ role: "user", content: "Explain OpenTelemetry in one sentence." },
],
},
}),
);
} finally {
await runtime.shutdown();
}
각 ID와 함께 선택적 표시 이름을 설정하려면 사용자와 고객을, 지원되는 모든 속성은 트레이스 컨텍스트를 참고하세요.
다중 턴 계측
단일 모델 호출만 추적할 땐 turn()이 필요 없어요. 대화 경계를 정의하고 싶을 때, 예를 들어 두 호출을 하나의 턴으로 묶고 싶을 때 사용하세요. 이후 턴에서 같은 스레드 ID를 재사용해 하나의 대화로 묶으면 돼요.
각 예제에는 초기화와 종료가 포함됩니다. 빠른 시작과 같은 환경 변수를 사용하세요.
Python
import os
from confident_trace import init, shutdown, turn
from openrouter import OpenRouter
init()
client = OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"])
try:
with turn("support-turn", thread_id="chat-42"):
context = client.chat.send(
model="openai/gpt-4o-mini",
messages=[
{
"role": "user",
"content": "List two useful facts about OpenTelemetry.",
}
],
)
answer = client.chat.send(
model="openai/gpt-4o-mini",
messages=[
{
"role": "user",
"content": f"Summarize these facts: {context.choices[0].message.content}",
}
],
)
finally:
shutdown()
TypeScript
import { OpenRouter } from "@openrouter/sdk";
import { init, turn } from "confident-trace";
const runtime = init();
const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY! });
try {
const answer = await turn({ name: "support-turn", threadId: "chat-42" }, async () => {
const context = await client.chat.send({
chatRequest: {
model: "openai/gpt-4o-mini",
messages: [
{ role: "user", content: "List two useful facts about OpenTelemetry." },
],
},
});
return client.chat.send({
chatRequest: {
model: "openai/gpt-4o-mini",
messages: [
{
role: "user",
content: `Summarize these facts: ${JSON.stringify(context)}`,
},
],
},
});
});
} finally {
await runtime.shutdown();
}
대화 그룹핑과 턴 속성은 스레드를 참고하세요.
트러블슈팅
Python
- 스팬 없음: 모델 호출 전에, 그리고 함수·바운드 메서드 별칭을 저장하기 전에
init()을 호출하세요. 프로세스 종료 전에shutdown()을 호출해 버퍼링된 스팬을 내보내세요. - 불완전한 스트림: shutdown 전에 스트림을 소비하거나 닫으세요.
- 게이트웨이 라벨 누락: 프록시 클라이언트를 쓸 때 정확한 base URL(경로 포함)을 등록하세요. OpenRouter와 Portkey 공용 OpenAI 엔드포인트는 자동 감지됩니다.
TypeScript
-
스팬 없음:
init()과--import confident-trace/register둘 다 사용하세요. 클라이언트 통합과 지원 SDK 버전은runtime.getInstrumentationStatus()로 확인하세요. -
불완전한 스트림: shutdown 전에 스트림을 소비하거나 취소하세요.
-
게이트웨이 라벨 누락: 구성된
*ProxyUrls항목이 경로 포함 정확히 클라이언트의baseURL과 일치하는지 확인하세요. -
콘텐츠 누락: 캡처 설정과 위 지원 API 목록을 확인하세요. 게이트웨이 측 exporter에는 별도의 콘텐츠 제어가 있어요.
-
중복 레코드: 같은 클라이언트 호출에 여러 instrumentor를 합치지 마세요. 클라이언트 계측과 게이트웨이 측 export가 한 요청에 대한 별도 뷰를 보고할 수도 있어요.
일반 설정 문제는 트러블슈팅을 참고하세요.
OpenRouter 계측 비활성화
특정 통합만 활성화하려면 init()에 통합 식별자 목록을 전달하세요. 빠른 시작은 Python·TypeScript 모두 "openrouter"를 사용합니다. OpenAI 프록시 클라이언트는 네이티브 게이트웨이 통합과 무관하게 "openai"를 사용해요. 빈 목록은 모든 자동 계측을 비활성화합니다.
Python
from confident_trace import init
init(instrumentations=())
# To enable only the quickstart integration: instrumentations=("openrouter",)
TypeScript
import { init } from "confident-trace";
init({ instrumentations: [] });
// To enable only the quickstart integration: instrumentations: ["openrouter"]
선택한 것을 시작 init() 호출에 적용하세요. SDK 훅을 제어하며 개별 게이트웨이 호스트는 제어하지 않고, 게이트웨이 자체의 export 설정은 바꾸지 않아요. 수동 설치한 TypeScript 어댑터에는 자체 복원 함수가 있습니다.
다음 단계
Online Evals
트레이스와 스팬이 Confident AI로 수집되는 대로 평가를 돌려 프로덕션 AI 품질을 모니터링하세요.
Threads
다중 턴 대화를 스레드로 묶고, 전체 대화를 하나의 단위로 평가하세요.
더 알아보기
- Portkey — 또 다른 AI 게이트웨이 추적
- Bifrost — OpenAI·Anthropic 호환 게이트웨이 추적
- Online Evals — 실시간 트레이스·스팬 평가