메인 콘텐츠로 건너뛰기
내장 전략 — cheapest, quality, balanced, adaptive — 는 가격과 품질로 모델을 선택합니다. Routing DSL은 그 아래 계층으로, 적합한 모델이 요청이 실제로 무엇인지에 따라 달라질 때를 위한 것입니다: 긴 에이전트형 코딩 턴, 저렴한 분류 호출, 비전 요청, 테스트 실패 후의 재시도 같은 경우입니다. 규칙을 작성하면 게이트웨이가 요청마다 평가하여 그에 따라 라우팅합니다. 이는 이름 지정 라우터dsl 전략입니다 — 따라서 애플리케이션은 계속 orcarouter/{name}을 호출하고 라우팅 로직은 대시보드에 위치하며, 버전 관리되고 재배포 없이 편집할 수 있습니다.

DSL을 사용해야 할 때

“가장 저렴한 라이브 모델” 또는 “최고 품질”이 의도를 담아낼 때는 내장 전략을 사용하세요. 라우팅이 요청의 내용이나 컨텍스트에 따라 달라질 때 DSL을 사용하세요:
  • 작업 특화 — 코드는 코딩 모델로, 비전은 비전 모델로, 저렴한 채팅은 저렴한 모델로 보냅니다.
  • 난이도 인식 라우팅 — 어려운 요청만 비싼 모델로 에스컬레이션하고, 쉬운 요청은 저렴하게 유지합니다.
  • 에이전트 인식 라우팅 — 세션 상태(에이전트가 어떤 도구를 사용했는지, 방금 테스트가 실패했는지, 몇 번째 턴인지)에 따라 다르게 라우팅합니다.
  • 시간 / 테넌트 / 헤더 규칙 — 시간, 사용자 그룹, 또는 요청 헤더별로 다르게 라우팅합니다.

활성화

대시보드의 Routing에서 라우터를 열고 StrategyDSL로 설정하세요. 그러면 이 라우터에 대한 DSL 편집기가 나타납니다. 라우터의 나머지 모든 것은 여전히 적용됩니다 — Allowed models glob, Default model 안전망, 그리고 orcarouter/{name} 호출 방식입니다.

편집기

편집기는 의도에서 작동하는 규칙셋까지 빠르게 도달하도록 만들어졌습니다:
  • Templates당신의 워크스페이스의 실제 모델로 시드됩니다(일회성 티어 매핑 대화상자를 통해). 따라서 빈 파일에서 시작하거나 “알 수 없는 모델” 벽에 부딪히지 않습니다.
  • Insert — 식별자를 손으로 입력하는 대신 자동완성에서 Model, Router(orcarouter/<name>), 또는 Pool을 끼워 넣습니다.
  • Generate — 원하는 라우팅을 일반 언어로 설명하면 실제 모델에 근거하여 컴파일되고 린트가 깨끗한 DSL을 받습니다.
  • Explain — 현재 규칙셋이 무엇을 하는지를 평이한 영어로 풀어 설명합니다.
  • Inline lint — 모든 오류는 {line, column, message}를 보고하며 모든 린트 코드에는 ? 설명기가 있습니다. 우선순위(첫 매칭 우선)와 일반적인 CEL 패턴이 현재 위치에 표시됩니다.

파일 구조

규칙셋은 세 개의 최상위 키를 가진 YAML입니다:
version: 1              # required — currently must be 1
rules: [...]            # required — 1 to 30 rules, evaluated in order
default: {...}          # required — the effect when no rule matches
규칙은 when: 조건과 use: 효과로 구성됩니다:
rules:
  - id: hard_code              # required: ^[a-z][a-z0-9_]{0,39}$, unique
    when: |                    # optional CEL boolean; absent ⇒ always matches
      task_class == "code" && difficulty > 0.6
    use:
      model: "anthropic/claude-sonnet-4-6"
default:
  delegate: balanced           # fall back to a built-in strategy
규칙은 위에서 아래로 평가되며, when:이 참인 첫 번째 규칙이 이깁니다. 일치하는 것이 없으면 default:가 적용됩니다. 가장 구체적인 규칙을 먼저 배치하세요 — 광범위한 초기 규칙은 그 아래 모든 것을 가립니다.

when: — 조건

조건은 CEL(Common Expression Language)로 작성됩니다: 설계상 안전합니다 — 루프 없음, I/O 없음, 마이크로초 단위 평가, RE2 정규식만 사용. 다음 여섯 가지 패턴이 실제 규칙의 대부분을 포괄합니다:
PatternExample
필드 접근task_class == "agent"
숫자 비교difficulty > 0.6 && request.input_tokens < 50000
불리언 로직agent_state.has_edited && !agent_state.has_run_tests
리스트 멤버십"Edit" in agent_state.tools_used
정규식 매크로system_prompt_matches("(?i)planning agent")
도구 매크로tool_calls_present_any(["Edit","Write","apply_patch"])

변수

요청 형태
VariableType
modelstring
request.input_tokensint
request.output_max_tokensint
request.streambool
request.visionbool
request.message_countint
request.has_system_promptbool
request.has_toolsbool
분류 (게이트웨이가 요청마다 계산)
VariableTypeMeaning
task_classstringchat / code / agent / vision / audio / rag / creative
difficultydouble0.01.0
code_keyword_densitydouble0.01.0
reasoning_cue_countint프롬프트에서 감지된 추론 신호
tool_countint요청상의 고유한 도구 정의 수
에이전트 세션 (agent_state.*, 대화 전반에 걸쳐 영속화됨)
VariableType
agent_state.turnint
agent_state.tools_usedlist<string>
agent_state.files_readlist<string>
agent_state.has_editedbool
agent_state.has_run_testsbool
agent_state.last_test_failedbool
agent_state.consecutive_errorsint
agent_state.elapsed_secondsint
agent_state.models_triedlist<string>
컨텍스트
VariableType
headers["x-foo"]string
user.id / user.groupint / string
token.id / token.nameint / string
time.hour / time.weekdayint (UTC)
workspace.idint

매크로

“요청 내부를 들여다보는” 일반적인 검사를 위해 등록된 CEL 함수입니다:
MacroReturns
system_prompt_matches(regex)결합된 시스템 메시지에 대한 RE2
user_message_matches(regex)마지막 사용자 메시지에 대한 RE2
tool_definitions_include(name)요청에 도구가 선언되어 있음
tool_calls_present_any(list)요청이 이들 중 어떤 도구 호출을 담고 있음
tool_results_from_any(list)요청에 이들 중 어떤 것에서 온 도구 역할 메시지가 있음
header_matches(name, regex)헤더 값에 대한 RE2

use: — 효과

use: 블록은 목적지(정확히 하나)와 임의 개수의 선택적 호출별 노브를 지정합니다.

목적지

use:
  model:    "anthropic/claude-sonnet-4-6"   # one upstream model
  models:   ["openai/gpt-4o-mini", "..."]   # load-balance across a list
  pool:     "@pool:<name>"                   # an admin-curated pool
  delegate: balanced                         # hand off to a built-in
                                             #   strategy: cheapest |
                                             #   quality | balanced |
                                             #   linucb | gated_adaptive
delegate: dsl은 거부됩니다(재귀가 발생할 것이기 때문). 특정 채널에 고정하는 것(channels: / @channel:)은 현재 사용할 수 없으며 지원되지 않음으로 린트됩니다 — 대신 model, models, 또는 pool로 라우팅하세요.

호출별 노브

업스트림 호출을 형성하기 위해 어떤 목적지와도 조합합니다:
use:
  reasoning_effort:       low | medium | high     # OpenAI o-series, Gemini
  thinking_budget_tokens: 1024..64000             # Claude / Gemini thinking
  samples:                1..16                    # the n parameter
  temperature:            0.0..2.0
  param_override:         { ... }                  # merged into upstream params
  header_override:        { ... }                  # merged into upstream headers
  reason_tag:             "<[a-z0-9_]+>"           # shows up in logs/telemetry
  affinity_ttl:           "5m"                      # channel stickiness window
  model_rewrite:          "<upstream-model>"       # send under a different name
param_overrideheader_override는 거부 목록을 강제합니다 — model, messages, stream, tools, 인증 헤더 등은 재정의할 수 없습니다 (이는 결제, 감사, 또는 에이전트 상태를 무력화할 수 있기 때문).

신뢰도 캐스케이드 및 앙상블 (고급)

두 가지 고급 효과를 통해 규칙이 약한 첫 응답에 반응하거나 여러 모델에 걸쳐 팬아웃할 수 있습니다. 이들은 다른 규칙과 동일한 방식으로 작성합니다. Cascade — 낮은 신뢰도 신호가 있을 때 더 강력한 효과로 재시도:
rules:
  - id: code_with_repair
    when: task_class == "code"
    use:
      model: "openai/gpt-4o-mini"
    on_low_confidence:
      signals: [patch_invalid, self_doubt, next_turn_test_failed]
      use:
        model: "anthropic/claude-sonnet-4-6"   # repair attempt
Ensemble — 여러 레그를 병렬로 실행하고 중재자가 선택하게 함:
use:
  parallel:
    - { model: "anthropic/claude-sonnet-4-6" }
    - { model: "openai/gpt-4o-mini", samples: 2 }
  arbiter:
    strategy: best_of_n        # or majority | first | tests_pass
    model:    "anthropic/claude-sonnet-4-6"   # judge (best_of_n only)
  max_latency_ms: 120000
앙상블 / 캐스케이드 런타임은 게이트되어 있으며 기본적으로 꺼져 있습니다. 각 병렬 레그와 각 캐스케이드 복구가 자체 호출로 청구되기 때문에, 팬아웃 런타임은 레그별 청구가 검증되는 동안 서버 플래그 뒤에 있습니다. 꺼져 있으면 parallel: 규칙은 첫 번째 레그만 제공하고 캐스케이드는 신호를 기록하지만 재디스패치하지 않습니다 — 규칙셋은 여전히 린트되고, 저장되고, 기본 효과를 정상적으로 라우팅합니다. 워크스페이스에 앙상블 런타임을 활성화하려면 문의하세요.

안전하게 배포하기

새 규칙셋은 저장하는 순간 트래픽을 넘겨받지 않습니다:
  • Shadow mode — 첫 저장 이후 일정 기간 동안 DSL은 평가되지만 사용되지 않습니다: 이전 전략이 여전히 트래픽을 제공하는 동안 게이트웨이는 DSL이 무엇을 했을지를 기록합니다. 대시보드는 diff 리포트를 보여줍니다 — 차이 나는 라우트의 비율, 예상 비용 델타, 규칙별 발화 횟수, 그리고 얼마나 자주 default:로 떨어졌는지. 규칙을 신뢰하기 전에 이를 읽어보세요.
  • Canary — DSL을 라이브 트래픽의 일정 비율(5 → 25 → 50 → 100)에 점진적으로 적용하면서 슬라이스별 메트릭을 관찰하고, 비율을 0으로 밀어 즉시 롤백합니다.
또한 편집기 안에서 바로 합성 요청(작업 클래스, 난이도, 에이전트 상태, 요청 형태)에 대해 규칙셋을 dry-run하고 트레이스와 매칭된 규칙을 볼 수 있습니다 — 트래픽 없음, 영속화되는 것 없음.

제한 및 검증

모든 저장은 엄격한 린트를 실행합니다; 유효하지 않은 규칙셋은 {line, column, message, rule}과 함께 거부됩니다:
  • Schema — 필수 키, 올바른 타입/열거값, 알 수 없는 필드 없음.
  • Size — ≤ 30개 규칙, ≤ 16 KiB YAML, when:당 ≤ 200자.
  • CEL — 파싱되고, 변수 환경에 대해 타입 검사되며, 알 수 없는 식별자 없음, when:은 반드시 bool로 평가되어야 함.
  • Effectuse: 블록당 정확히 하나의 목적지; 모든 model / models / @pool: 참조는 워크스페이스 내에서 해결되어야 함.
  • Knob rangesthinking_budget_tokens ∈ [1024, 64000], temperature ∈ [0, 2], samples ∈ [1, 16].
  • Reserved_로 시작하는 규칙 id는 예약됨; 규칙 id로서의 default는 거부됨(최상위 default: 블록을 사용하세요).
모든 저장과 롤백은 감사 행을 기록합니다; 동시 편집은 감지되며 두 번째 저장은 최신 상태에 대해 재시도하도록 요청받습니다.

완전한 예시

version: 1
rules:
  - id: vision
    when: request.vision
    use: { model: "openai/gpt-4o" }

  - id: cheap_chat
    when: task_class == "chat" && difficulty < 0.3
    use: { delegate: cheapest }

  - id: hard_code
    when: task_class == "code" && difficulty > 0.6
    use:
      model: "anthropic/claude-sonnet-4-6"
      thinking_budget_tokens: 8000
      reason_tag: hard_code

  - id: agent_after_failed_test
    when: agent_state.last_test_failed && agent_state.consecutive_errors >= 2
    use:
      model: "anthropic/claude-sonnet-4-6"
      reason_tag: repair

default:
  delegate: balanced
요청이 어떤 모델로 해결되었는지 확인하려면 X-Orca-RouterX-Orca-Resolved-Model 응답 헤더를 읽으세요.

API 레퍼런스

DSL은 라우터별로 관리됩니다; 쓰기에는 **Developer+**가 필요합니다.
Method & pathRolePurpose
GET /api/user/routers/:id/dslMember소스 + 버전 + 섀도/카나리아 상태.
PUT /api/user/routers/:id/dslDeveloper+린트 + 저장(새 버전, 감사됨).
POST /api/user/routers/:id/dsl/lintMember초안 린트 → {errors:[…]}.
POST /api/user/routers/dsl/lintMember무상태 린트(라우터 id 없음).
POST /api/user/routers/:id/dsl/dryrunMember합성 요청 평가 → 트레이스 + 매칭된 규칙.
GET /api/user/routers/:id/dsl/historyMember버전 이력, 최신순.
POST /api/user/routers/:id/dsl/rollback/:versionDeveloper+재린트 후 이전 버전 복원.

FAQ

이것은 하나의 전략입니다 — cheapest / quality / balanced / adaptive와 나란히 있는 dsl 옵션입니다. 나머지는 가격과 품질로 선택하고, DSL은 요청의 형태, 분류, 에이전트 상태에 대해 작성한 규칙으로 선택합니다. 규칙의 효과로서 또는 기본값으로서 여전히 내장 전략에 delegate:할 수 있습니다.
최상위 default: 효과가 적용됩니다. 이는 필수이므로 항상 정의된 결과가 있습니다 — 일반적으로 delegate: balanced 또는 특정 안전망 모델입니다.
네. CEL은 표준 라이브러리 함수만 있는 샌드박스에서 실행되며, 몇 밀리초의 평가 데드라인, RE2 정규식(선형 시간, ReDoS 없음), 그리고 데이터베이스, 네트워크, 또는 파일시스템에 대한 접근이 없습니다. 변수 환경은 고정된 스칼라와 리스트 집합입니다.
세 가지 방법이 있습니다: 편집기에서 합성 요청에 대해 dry-run하기, shadow mode로 두고 diff 리포트 읽기, 그런 다음 100%로 올리기 전에 라이브 트래픽의 작은 비율에 canary 적용하기.