Larry Profe — portando a Larry a Math Challenge
Resumen ejecutivo
Larry ya existe en IOS como copiloto EN/ES sobre Workers AI (kimi-k2.6 → gpt-oss-120b → respuesta enlatada), con un prompt de sistema bilingüe único, un protocolo de "tool calling" hecho a mano (JSON en una línea) y auditoría durable en D1. Nada de esto usa la API de Claude — sería la primera integración de Claude en este repo.
El dueño ya decidió: Larry Profe usa la API de Claude con ruteo por dificultad (Haiku/Sonnet/Opus). El precedente más cercano en el repo no es el chat libre sino src/larry/contador/explain.ts: un hallazgo determinístico entra, un LLM lo explica en lenguaje natural sin recalcular nada, con fallback a plantilla. Larry Profe debe seguir exactamente ese patrón: el motor de calificación decide qué está bien o mal; Claude solo explica, en el idioma, edad y tono correctos, nunca avergonzando al niño.
Este documento fue traducido del original en inglés por Claude (Anthropic) y verificado automáticamente contra la fuente: cada número, URL, marcador de cita y marca [unverified] coincide con el original. La prosa todavía no ha sido revisada por un hablante nativo humano.
Estado de verificación
Este documento no lleva ninguna marca [unverified]. Cada afirmación está atada a una fuente numerada de abajo.
[unverified] quiere decir que la afirmación está en la investigación pero no se confirmó contra una fuente primaria en la sesión que la produjo. Se publica en vez de borrarse, porque un corpus que esconde sus huecos no es verificable.
Cómo se produjo esta investigación
Los 47 documentos se hicieron el 2026-07-31 por agentes independientes, cada uno con instrucción explícita de no inventar citas y de marcar como [unverified] lo que no pudiera confirmar contra una fuente primaria. La cuota de búsqueda web de la sesión se agotó a media investigación y los agentes posteriores trabajaron por descarga directa contra fuentes primarias. Varios sitios (ftc.gov, ico.org.uk) bloquean la descarga automatizada, y por eso ciertas afirmaciones legales están marcadas a propósito.
Esto es investigación, no asesoría legal, médica ni financiera. Nada aquí reclama un resultado de aprendizaje de Math Challenge; ese estudio todavía no existe.
Qué existe hoy — rutas de archivo y referencias de línea de este repo
- Persona/canon.
docs/larry.md:1-16— “rinoceronte naranja, entrenador honesto,” con la frase distintiva “¡Ya vas!” solo al aceptar una tarea, y humor que nunca apunta a nadie más que a sí mismo. - La cadena de modelos es Workers AI, no Claude.
src/larry/chat.ts:40-41:PRIMARY_MODEL = '@cf/moonshotai/kimi-k2.6',FALLBACK_MODEL = '@cf/openai/gpt-oss-120b'(el mismo par ensrc/larry/contador/explain.ts:16-17).docs/wiki/decisions.md:42-47(ADR-006): “nuestro propio modelo (Workers AI) atiende el 70–90% del tráfico rutinario; una API de frontera atiende los casos difíciles” más una caché semántica y un presupuesto por rol — una forma conceptualmente similar a lo que necesita Larry Profe, pero IOS prioriza Workers AI con Claude como desborde; el brief del dueño para Math Challenge prioriza Claude con ruteo por dificultad del problema, que no es la misma política. - Patrón de prompt único bilingüe.
src/larry/prompts.ts:24-57,buildSystemPrompt(locale, context)— cada línea de persona/regla está escrita dos veces, EN y luego ES, en un solo string (p. ej.:29); solo la instrucción “responde en el idioma X” (:47) es específica del locale. No escala a 5 idiomas (ver abajo). - Lista rígida de “nunca”.
src/larry/prompts.ts:38-44— cinco viñetas: nunca borrar datos del cliente, nunca leer contenido de objetos, nunca tocar facturación sin confirmación, nunca crear/rotar llaves por chat, nunca cambiar código/configuración; reafirmada en prosa endocs/larry.md:96-102(§4.2). Este es el espacio de plantilla donde Larry Profe necesita sus propias reglas de seguridad infantil. - Protocolo de herramientas hecho a mano. El modelo debe responder solo con una línea
{"tool": "<name>", "args": {...}}(prompts.ts:50-51), no con los bloques de contenidotool_usede Anthropic. Se parsea conparseToolCall(chat.ts:273-289); se itera congenerateReplyWithTools(:236-267), tope enMAX_TOOL_HOPS = 2(:44). La seguridad de alcance por tenant vive ensrc/larry/tools.ts:47-48, 342-394. - Cadena de respaldo, sin reintento/backoff.
chat.ts:295-314generateReplyintenta cada modelo una vez, y cae acannedErrorReply(locale)(prompts.ts:67-71) si ambos fallan. - Sumidero de auditoría.
migrations/0011_larry_audit.sql:5-23— tabla D1, tipos de filachat/tool, columnas que incluyentenant_id,locale,tools_used,outcome,latency_ms,prompt_tokens,completion_tokens. Los escritoressrc/larry/audit.ts:36-67, 70-97son de mejor esfuerzo, nunca lanzan excepción. Los conteos de tokens son una estimación burda detext.length / 4(audit.ts:31-33), no elusagereal del modelo — las respuestas de Claude traen conteos exactos de tokens, que la auditoría de Larry Profe debería registrar con precisión en vez de estimarlos. - La detección de locale es solo EN/ES.
src/larry/locale.ts:9, 63-71— una lista de palabras en español codificada a mano más una verificación de caracteres acentuados; el inglés es el valor por omisión. No existe infraestructura FR/PT/DE; extender esta heurística es frágil (ver abajo). - El precedente real:
src/larry/contador/explain.ts.:67-75la regla rígida del prompt de sistema (“Every number… MUST appear verbatim in the provided JSON. Never compute, convert, round, or invent a figure… Temperature is 0.”);:106-145explainFinding()quita el campoexplanationya precalculado antes de enviarle al modelo el hallazgo (:113, para que no pueda simplemente repetir un string enlatado), pide JSON bilingüe{"en":..., "es":...}, y cae arenderTemplateExplanation()(:41-60) — un volcado de hechos plano, sin LLM — ante cualquier falla. Esto es arquitectónicamente lo que Larry Profe necesita. - Avatar + máquina de estados.
packages/design-system/larry/LarryAvatar.tsx:4-13— estadosorb|face|idle|thinking|working|happy|denying|celebrating|presenting;larry.css:1-121un@keyframespor estado, deshabilitado bajoprefers-reduced-motion(:113-120).packages/design-system/src/larry-chat/useLarryChat.ts:1-9,30documentaidle → thinking → working → idle. Reutilizable tal cual para Larry Profe. - No hay uso de la API de Claude en ninguna parte de este repo hoy — no hay ningún import de
@anthropic-ai/sdkbajosrc/nipackages/. Esta es una primera integración, no una extensión.
Qué debe cambiar para un tutor de matemáticas para niños
- Tono, no “entrenador honesto.” La persona de IOS apunta a ingenieros adultos B2B que pueden recibir una corrección directa. Un niño nunca debe sentirse avergonzado — más estricto que “el humor nunca se burla de las características de una persona.”
- Cinco idiomas, no dos. El tipo
'en'|'es'delocale.tsy su detector por lista de palabras no se extienden a FR/PT/DE, y el patrón deprompts.tsde “escribir cada línea dos veces” multiplicaría por 5 los tokens del prompt para contenido que en su mayoría no se usa en cada llamada — mejor construir un prompt de un solo idioma por locale. - La corrección matemática no puede depender del LLM. Una respuesta incorrecta de una herramienta de IOS es una mala pista de UI; una explicación incorrecta de Larry Profe enseña matemáticas erróneas de forma activa. Esta es exactamente la razón por la que la forma “el LLM explica, nunca calcula” de
contador/explain.tses correcta y el ciclo libre dechat.tsno lo es. - Vocabulario por edad, explícito en el prompt (banda de edad como parámetro), no dejado a que el modelo lo infiera del tono.
- El ruteo por modelo es nuevo — ADR-006 describe un ruteo híbrido con prioridad Workers AI; Larry Profe lo invierte (prioridad Claude, tres niveles de dificultad, sin Workers AI), según el brief del dueño.
- Retirar o suavizar el estado de avatar
denyingpara un producto infantil — el lenguaje corporal de negar con la cabeza (larry.css:87-98) se lee como “estás mal”; preferirthinking→presentingpara las correcciones.
Tabla de ruteo por modelo
Los precios/IDs de modelo vienen de la skill claude-api (en caché desde 2026-06-24; el precio de introducción de Sonnet 5 corre hasta el 2026-08-31), no de memoria de entrenamiento. Las estimaciones de costo asumen un prefijo de prompt de sistema compartido (cubierto bajo caché abajo) más una carga útil por llamada de {problema, pasos del estudiante, veredicto de calificación}; las cifras son estimaciones a validar contra prompts reales, no mediciones.
| Banda de dificultad | ID de modelo | $/MTok entrada / salida | Tokens estimados entrada → salida | Costo estimado / 1,000 explicaciones | Meta de latencia |
|---|---|---|---|---|---|
| Aritmética básica | claude-haiku-4-5 | $1.00 / $5.00 | ~300 → ~150 | ~$1.05 | < 1.5 s, sin necesidad de streaming |
| Nivel medio (fracciones, álgebra, geometría) | claude-sonnet-5 | $3.00 / $15.00 (intro $2/$10 hasta 2026-08-31) | ~500 → ~300 | ~$6.00 (intro ~$4.00) | 2–4 s, streaming si > ~3 s |
| Avanzado (cálculo tensorial, integrales dobles, demostraciones) | claude-opus-5 | $5.00 / $25.00 | ~800 → ~600 + razonamiento adaptativo | ~$19 de piso, realistamente $35–60 una vez contados los tokens de razonamiento | 5–15 s; debe usar streaming |
Notas:
- El costo de Opus 5 está dominado por los tokens de razonamiento. Según la skill, el razonamiento está activado por omisión en Opus 5 — una solicitud que nunca configura
thinkingde todos modos razona, y el razonamiento se factura como salida a $25/MTok. Una explicación difícil puede gastar 1,000–2,000 tokens de razonamiento antes de la respuesta de 600 tokens, lo que añade ~$25–50 por cada 1,000 llamadas solo por eso. Deshabilitar el razonamiento tiene fallas reales (llamadas a herramientas o etiquetas<thinking>filtrándose al texto visible, segúnshared/model-migration.md), así que la palanca más segura esoutput_config.effort— empezar Opus 5 enmediumy subirlo solo si la evaluación muestra explicaciones superficiales. - Haiku 4.5 necesita un prefijo cacheable de 4,096 tokens. Según la tabla de mínimos por modelo de
shared/prompt-caching.md, el piso de Haiku 4.5 es 4,096 tokens (el más alto de cualquier modelo actual; Opus 5/Fable 5 necesitan solo 512). Un prompt de sistema de aritmética básica (persona + reglas + una banda de edad + un idioma) probablemente queda muy por debajo de eso, lo que significa que las llamadas a Haiku podrían nunca activar el caché de prompt a menos que el prefijo se rellene deliberadamente — hay que señalarle esto al dueño en vez de asumir que el caché “simplemente funciona” en el nivel más barato. - La API por lotes (Batch, 50% de descuento) sirve para la pregeneración, no para tráfico en vivo. Una explicación en vivo dentro de una sesión no puede ir por lotes, pero pregenerar los N conceptos erróneos más comunes por tema/edad/idioma antes del lanzamiento es exactamente el caso de uso de la API por lotes (hasta 100K solicitudes por lote, no sensible a latencia).
La arquitectura del prompt — esqueleto propuesto, 5 idiomas, reglas rígidas
Apartándose del patrón de “cada línea dos veces” de prompts.ts, construir un prompt por (locale, banda de edad, nivel), mostrado en inglés (FR/PT/DE/ES son renders paralelos de un solo idioma, no concatenaciones):
You are Larry Profe, Larry the orange rhinoceros, teaching math to
[AGE_BAND] students. Same character as always — just teaching math now.
WHAT YOU RECEIVE: a JSON verdict from the grading engine (problem, student
steps, which were correct, where the error started, its classification).
You do NOT grade or recompute. Every number/step you reference MUST come
verbatim from that JSON.
WHAT YOU DO:
1. Say specifically what the student did right (not just "good job").
2. Explain what went wrong and why — the real misconception, not "wrong answer."
3. Walk through the correct process, like a patient professor, at a level a
[AGE_BAND] student can follow.
4. End on encouragement, never on the mistake.
HARD RULES:
- Never call a student "bad at math," "slow," or any variant — mistakes are
how math is learned.
- Never use sarcasm, exasperation, or a disappointed tone, even softened.
- Never invent or alter a number/step/verdict not in the provided JSON.
- Never compare the student to other students or a class average.
- Never skip "what you did right," even if everything was wrong — find
something true and specific (effort, a correct partial step, right
approach/wrong arithmetic).
- If asked something outside math tutoring, redirect kindly to a
parent/teacher.
LANGUAGE: Reply only in [LOCALE_NAME]. Never mix languages or offer translation.
VOCABULARY: [age-band guidance — e.g. ages 6-8: concrete objects, no jargon;
ages 13+: precise terminology expected.]
Reservar output_config.format / esquemas strict: true para el traspaso motor-de-calificación → Larry-Profe (el propio backend de Math Challenge valida ese JSON, no Claude) — la salida de este prompt es prosa simple en streaming, no datos estructurados.
Estrategia de caché y control de costo
Dos capas independientes:
- Caché de prompt de Claude sobre el prefijo estable (persona + reglas + un idioma + una banda de edad). Por modelo, por prefijo — las escrituras cuestan 1.25× (TTL de 5 min) o 2× (1 hora), las lecturas ~0.1×. Un TTL de 1 hora con precalentamiento periódico (solicitudes
max_tokens: 0, segúnshared/prompt-caching.md) conviene al tráfico de horas de tarea, que llega en ráfagas. Omitir para Haiku a menos que el prefijo supere los 4,096 tokens (ver arriba). - Caché de conceptos erróneos a nivel de aplicación (D1/KV) — el mecanismo que el brief del dueño realmente pide. Cachear la explicación generada completa, indexada por
(topic, misconception-classification, age-band, locale)— no la instancia exacta del problema, para que distintos problemas de fracciones con el mismo error de “olvidó el denominador común” acierten en la misma entrada de caché. Refleja el patrón estático existente de búsquedaS3_ERROR_KB/METRIC_KB(src/larry/tools.ts:59-135), excepto que se puebla con salida de Claude al momento de generarse; si falla, hacer una llamada en vivo y poblar el caché, reflejando la forma AI-luego-plantilla decontador/explain.ts. Registrarcache_hit: booleany elusage.input_tokens/usage.output_tokensreal en una tabla de auditoría análoga a la migración0011— no la estimacióntext.length/4que usa hoyaudit.ts. - API por lotes para la siembra en frío — pregenerar los N conceptos erróneos más comunes por tema antes del lanzamiento con 50% de descuento, convirtiendo la mayor parte del tráfico temprano en lecturas de caché desde el día uno.
Implicaciones de diseño
- Larry Profe es una nueva integración con la API de Claude; no enrutarla a través del gateway de Workers AI de IOS — el dueño quiere Claude, y ADR-006 es una arquitectura distinta, con prioridad Workers AI, para un producto distinto.
- Modelar el motor de calificación como fuente de verdad, Claude solo-explica — seguir la forma de
contador/explain.ts, no el ciclo libre de herramientas dechat.ts. - Descartar el patrón de prompt bilingüe en línea; un prompt por locale, ya que 5 idiomas hace que la deriva entre idiomas dentro de un solo prompt sea a la vez costosa y propensa a errores.
- Tomar el locale como un parámetro explícito del cliente (Math Challenge ya tiene una configuración de idioma) en vez de inferirlo como lo hace
locale.tspara IOS. - Construir el ruteador de nivel de dificultad en el backend de Math Challenge (junto a la calificación, que ya sabe tema/nivel) — nunca dejar que Claude elija su propio nivel de modelo.
- Tratar
effortcomo un segundo eje de ruteo independiente de la elección del modelo; empezar conservador (mediumen Opus 5) ya que es la palanca principal contra el disparo de costo por tokens de razonamiento. - Registrar los campos
usagereales de Claude en el sumidero de auditoría desde el día uno en vez de repetir la estimación por conteo de caracteres deaudit.ts. - Escribir un canon de reglas rígidas de seguridad infantil paralelo a la lista de cinco puntos de
docs/larry.md§4.2, pero desde cero — las reglas de IOS son sobre seguridad de datos, no seguridad emocional. - Reutilizar
LarryAvatary su máquina de estados sin cambios, pero reconsiderar sidenyingdebería siquiera dispararse frente a un niño. - Mantener el caché de conceptos erróneos y el caché de prompt de Claude como sistemas distintos — resuelven problemas diferentes (evitar reenviar el prefijo vs. evitar regenerar salida semánticamente idéntica) y confundirlos entrega menos del objetivo de “una generación, no mil”.
- Usar la API por lotes para presembrar el caché de conceptos erróneos antes del lanzamiento y para rellenar nuevos tipos de conceptos erróneos encontrados en producción.
- Cada regla rígida y línea de prompt necesita copia EN/ES/FR/PT/DE revisada por humanos — un tono que se lee como alentador en un idioma puede aterrizar como condescendiente en otro; no dejar esto a la traducción en tiempo de ejecución.
Preguntas abiertas para el dueño del proyecto
- ¿El ruteador de nivel de dificultad vive en el backend de Math Challenge (el motor de calificación etiqueta tema/nivel), o Larry Profe debería reclasificar la dificultad a partir del texto del problema?
- ¿Cuáles son las bandas de edad reales (K-2/3-5/6-8/9-12, o por grado)? Esto determina tanto las variantes de vocabulario como el número de combinaciones de prompt cacheadas a redactar (locale × banda-de-edad × nivel podría ser 5×4×3 = 60).
- ¿El
effortde Opus 5 debería ser fijo por nivel, o ajustable por tema dentro de “avanzado” (una integral doble y una demostración completa de cálculo tensorial plausiblemente necesitan distinto esfuerzo)? - ¿Existe un presupuesto de latencia a nivel de producto (p. ej. “debe empezar a transmitirse en 2 s o mostrar un estado de carga”) que debería condicionar el streaming por omisión por nivel?
- ¿Quién revisa la copia de reglas rígidas y prompts en FR/PT/DE — un revisor de contenido educativo multilingüe, o traducción automática como primer borrador a partir de la versión EN/ES?
- ¿El caché de conceptos erróneos necesita un TTL, o está bien servir indefinidamente una explicación cacheada para un concepto erróneo raro?
- ¿“Lo que el estudiante hizo bien” siempre debe encontrar algo, incluso para una respuesta en blanco/adivinada — y si es así, cuál es el piso honesto (p. ej. “lo intentaste”)?
Fuentes
Este documento cita archivos del repositorio y otras investigaciones, no una lista numerada de fuentes.
Preguntas que este documento le deja abiertas al dueño
Están sin responder a propósito. Se listan, no se resuelven — convertirlas en preguntas frecuentes obligaría a inventar respuestas que el documento no tiene.
- Does the difficulty-tier router live in Math Challenge's backend (grading engine tags topic/tier), or should Larry Profe re-classify difficulty from problem text?
- What are the actual age bands (K-2/3-5/6-8/9-12, or by grade)? This drives both vocabulary variants and the number of cached prompt combinations to author (locale × age-band × tier could be 5×4×3 = 60).
- Should Opus 5's effort be fixed per tier, or tunable per-topic within "advanced" (a double integral and a full tensor-calculus proof plausibly need different effort)?
- Is there a product-level latency budget (e.g. "must start streaming within 2s or show a loading state") that should gate default streaming per tier?
- Who reviews the FR/PT/DE hard-rule and prompt copy — a multilingual education content reviewer, or machine translation as a first draft from the EN/ES version?
- Does the misconception cache need a TTL, or is a cached explanation for a rare misconception fine to serve indefinitely?
- Must "what the student did right" always find something, even for a blank/guessed answer — and if so, what's the honest floor (e.g. "you tried")?
Uno de 51 documentos de investigación, 168,346 palabras en total, contadas en el build sobre los archivos mismos. Leer este documento en el repositorio