dsl de un enrutador nombrado — así
que tu aplicación sigue llamando a orcarouter/{name} y la lógica de enrutamiento
vive en el panel, versionada y editable sin un redespliegue.
Cuándo recurrir al DSL
Usa una estrategia integrada cuando “el modelo en vivo más barato” o “la mejor calidad” captura tu intención. Recurre al DSL cuando el enrutamiento depende del contenido o contexto de la solicitud:- Especialización por tarea — envía código a un modelo de codificación, visión a un modelo de visión, chat barato a un modelo barato.
- Enrutamiento consciente de la dificultad — escala solo las solicitudes difíciles a un modelo caro; mantén las fáciles baratas.
- Enrutamiento consciente del agente — enruta de forma distinta según el estado de la sesión (qué herramientas ha usado el agente, si las pruebas acaban de fallar, cuántos turnos lleva).
- Reglas por tiempo / inquilino / cabecera — enrutamiento distinto por hora, grupo de usuarios o una cabecera de la solicitud.
Cómo habilitarlo
En el panel, bajo Routing, abre un enrutador y configura su Estrategia a DSL. Eso revela el editor de DSL para este enrutador. Todo lo demás del enrutador sigue aplicándose — el glob de Modelos permitidos, la red de seguridad de Modelo por defecto y la invocaciónorcarouter/{name}.
El editor
El editor está construido para llevarte de la intención a un conjunto de reglas funcional rápidamente:- Templates sembradas con los modelos reales de tu espacio de trabajo (vía un diálogo único de mapeo de niveles), para que nunca empieces desde un archivo en blanco ni choques con un muro de “modelo desconocido”.
- Insert — inserta un Model, un Router (
orcarouter/<name>) o un Pool desde el autocompletado en lugar de teclear identificadores a mano. - Generate — describe el enrutamiento que quieres en lenguaje sencillo y obtén de vuelta DSL compilado y limpio de lint, fundamentado en tus modelos reales.
- Explain — una paráfrasis en español sencillo de lo que hace el conjunto de reglas actual.
- Lint en línea — cada error reporta
{line, column, message}y cada código de lint tiene un explicador?. La precedencia (gana la primera coincidencia) y los patrones CEL comunes se muestran in situ.
Estructura del archivo
Un conjunto de reglas es YAML con tres claves de nivel superior:when: y un efecto use::
when: sea
verdadero. Si ninguna coincide, se aplica default:. Ordena tus reglas de la más
específica primero — una regla amplia temprana eclipsa todo lo que está debajo.
when: — la condición
Las condiciones se escriben en CEL
(Common Expression Language): seguro por diseño — sin bucles, sin E/S, evaluación
en microsegundos, solo regex RE2. Estos seis patrones cubren la gran mayoría de las
reglas reales:
| Patrón | Ejemplo |
|---|---|
| Acceso a campo | task_class == "agent" |
| Comparación numérica | difficulty > 0.6 && request.input_tokens < 50000 |
| Lógica booleana | agent_state.has_edited && !agent_state.has_run_tests |
| Pertenencia a lista | "Edit" in agent_state.tools_used |
| Macro de regex | system_prompt_matches("(?i)planning agent") |
| Macro de herramienta | tool_calls_present_any(["Edit","Write","apply_patch"]) |
Variables
Forma de la solicitud| Variable | Tipo |
|---|---|
model | string |
request.input_tokens | int |
request.output_max_tokens | int |
request.stream | bool |
request.vision | bool |
request.message_count | int |
request.has_system_prompt | bool |
request.has_tools | bool |
| Variable | Tipo | Significado |
|---|---|---|
task_class | string | chat / code / agent / vision / audio / rag / creative |
difficulty | double | 0.0–1.0 |
code_keyword_density | double | 0.0–1.0 |
reasoning_cue_count | int | señales de razonamiento detectadas en el prompt |
tool_count | int | definiciones de herramientas distintas en la solicitud |
agent_state.*, persistido a lo largo de una conversación)
| Variable | Tipo |
|---|---|
agent_state.turn | int |
agent_state.tools_used | list<string> |
agent_state.files_read | list<string> |
agent_state.has_edited | bool |
agent_state.has_run_tests | bool |
agent_state.last_test_failed | bool |
agent_state.consecutive_errors | int |
agent_state.elapsed_seconds | int |
agent_state.models_tried | list<string> |
| Variable | Tipo |
|---|---|
headers["x-foo"] | string |
user.id / user.group | int / string |
token.id / token.name | int / string |
time.hour / time.weekday | int (UTC) |
workspace.id | int |
Macros
Funciones CEL registradas para las comprobaciones comunes de “mirar dentro de la solicitud”:| Macro | Devuelve |
|---|---|
system_prompt_matches(regex) | RE2 sobre los mensajes de sistema unidos |
user_message_matches(regex) | RE2 sobre el último mensaje de usuario |
tool_definitions_include(name) | una herramienta está declarada en la solicitud |
tool_calls_present_any(list) | la solicitud lleva alguna de estas llamadas a herramientas |
tool_results_from_any(list) | la solicitud tiene mensajes con rol de herramienta de alguno |
header_matches(name, regex) | RE2 sobre el valor de una cabecera |
use: — el efecto
Un bloque use: nombra un destino (exactamente uno) y cualquier número de
perillas opcionales por llamada.
Destino
delegate: dsl se rechaza (haría recursión). Fijar a canales específicos
(channels: / @channel:) no está disponible actualmente y el lint lo marca como
no soportado — enruta por model, models o pool en su lugar.Perillas por llamada
Combínalas con cualquier destino para dar forma a la llamada upstream:param_override y header_override aplican una lista de denegación — no puedes
sobrescribir model, messages, stream, tools, cabeceras de autenticación,
etc. (eso subvertiría la facturación, la auditoría o el estado del agente).
Cascadas de confianza y ensembles (avanzado)
Dos efectos avanzados permiten que una regla reaccione a una primera respuesta débil o se despliegue en abanico entre varios modelos. Se escriben de la misma forma que cualquier regla. Cascade — reintenta ante una señal de baja confianza con un efecto más fuerte:El runtime de ensemble / cascade está restringido y desactivado por defecto.
Como cada rama paralela y cada reparación en cascada se factura como su propia
llamada, el runtime de despliegue en abanico está detrás de un flag de servidor
mientras se valida la facturación por rama. Con él desactivado, una regla
parallel: sirve solo la primera rama y una cascade registra su señal pero no
vuelve a despachar — el conjunto de reglas igualmente pasa el lint, se guarda y
enruta su efecto principal con normalidad. Contáctanos para habilitar el runtime de
ensemble en tu espacio de trabajo.Despliegue seguro
Un nuevo conjunto de reglas no se hace cargo de tu tráfico en el momento en que lo guardas:- Modo shadow — durante una ventana tras el primer guardado, el DSL se evalúa
pero no se usa: tu estrategia anterior sigue sirviendo el tráfico mientras la
pasarela registra lo que el DSL habría hecho. El panel muestra un informe de
diferencias — porcentaje de rutas divergentes, delta de coste proyectado, conteos
de disparo por regla y con qué frecuencia cayó hasta
default:. Léelo antes de confiar en las reglas. - Canary — sube gradualmente el DSL a un porcentaje del tráfico en vivo (5 → 25 → 50 → 100), observando las métricas por porción, y revierte al instante deslizando el porcentaje a 0.
Límites y validación
Cada guardado ejecuta un lint estricto; los conjuntos de reglas inválidos se rechazan con{line, column, message, rule}:
- Esquema — claves requeridas, tipos/enums correctos, sin campos desconocidos.
- Tamaño — ≤ 30 reglas, ≤ 16 KiB de YAML, ≤ 200 caracteres por
when:. - CEL — parsea, verifica tipos contra el entorno de variables, sin
identificadores desconocidos, y
when:debe evaluar a un bool. - Efecto — exactamente un destino por bloque
use:; todas las referenciasmodel/models/@pool:deben resolverse en tu espacio de trabajo. - Rangos de perillas —
thinking_budget_tokens ∈ [1024, 64000],temperature ∈ [0, 2],samples ∈ [1, 16]. - Reservado — los ids de regla que empiezan con
_están reservados;defaultcomo id de regla se rechaza (usa el bloquedefault:de nivel superior).
Un ejemplo completo
X-Orca-Router y X-Orca-Resolved-Model
response headers.
Referencia de la API
El DSL se gestiona por enrutador; las escrituras requieren Developer+.| Método y ruta | Rol | Propósito |
|---|---|---|
GET /api/user/routers/:id/dsl | Member | Fuente + versión + estado shadow/canary. |
PUT /api/user/routers/:id/dsl | Developer+ | Lint + guardar (nueva versión, auditada). |
POST /api/user/routers/:id/dsl/lint | Member | Hacer lint de un borrador → {errors:[…]}. |
POST /api/user/routers/dsl/lint | Member | Lint sin estado (sin id de enrutador). |
POST /api/user/routers/:id/dsl/dryrun | Member | Evaluar una solicitud sintética → traza + regla coincidente. |
GET /api/user/routers/:id/dsl/history | Member | Historial de versiones, la más nueva primero. |
POST /api/user/routers/:id/dsl/rollback/:version | Developer+ | Volver a hacer lint y restaurar una versión anterior. |
Preguntas frecuentes
¿En qué se diferencia esto de la estrategia de un enrutador nombrado?
¿En qué se diferencia esto de la estrategia de un enrutador nombrado?
Es una estrategia — la opción
dsl junto a cheapest / quality / balanced /
adaptive. Las demás eligen por precio y calidad; el DSL elige según reglas que
tú escribes sobre la forma de la solicitud, la clasificación y el estado del
agente. Aun así puedes hacer delegate: a una estrategia integrada como efecto
de una regla o como el default.¿Qué pasa si ninguna regla coincide?
¿Qué pasa si ninguna regla coincide?
Se aplica el efecto
default: de nivel superior. Es requerido, así que siempre
hay un resultado definido — comúnmente delegate: balanced o un modelo de red
de seguridad específico.¿Es seguro ejecutar CEL no confiable en la ruta crítica?
¿Es seguro ejecutar CEL no confiable en la ruta crítica?
Sí. CEL se ejecuta en un sandbox solo con funciones de la biblioteca estándar,
una fecha límite de evaluación de unos pocos milisegundos, regex RE2 (tiempo
lineal, sin ReDoS) y sin acceso a la base de datos, la red o el sistema de
archivos. El entorno de variables es un conjunto fijo de escalares y listas.
¿Puedo probar un conjunto de reglas antes de que toque tráfico real?
¿Puedo probar un conjunto de reglas antes de que toque tráfico real?
Tres formas: hazle un dry-run contra una solicitud sintética en el editor,
déjalo en modo shadow y lee el informe de diferencias, y luego haz un
canary sobre un pequeño porcentaje del tráfico en vivo antes de subirlo
al 100%.
