English · Español
Lab 00 — Tools tipadas¶
Objetivo: implementar las cuatro tools §A13 como funciones Python planas con descriptores JSON-Schema. Sin MCP (Model Context Protocol) todavía — solo las tools.
Tiempo estimado: 2–3 horas.
Prereq: la tabla de verdad de conjugación §A13 de la Fase 12 disponible como
data/processed/conjugation_table.json(o donde sea que la Fase 12 la haya producido).
Qué produces¶
Un directorio experiments/31-typed-tools/ que contiene:
demo.py— instancia cada tool e imprime un pequeño transcript de smoke-test.results.json—{tools_registered: 4, smoke_test_pass: true}.manifest.json— segúnLYNX_CORTEX.md§5.
Más, en src/miniagent/tools/:
__init__.py— registro + decorador@register.base.py— dataclassTool.conjugate.py— implementaconjugate.lookup_irregular_verb.py— implementalookup_irregular_verb.lookup_spanish.py— implementalookup_spanish.check_subject_verb_agreement.py— implementacheck_subject_verb_agreement.
TODOs¶
Bloque A — la dataclass Tool¶
En src/miniagent/tools/base.py:
- Define una dataclass frozen:
- Define un tipo de excepción
ToolErrorpara errores a nivel de tool (inputs fuera de alcance, datos faltantes). - Define un decorador
registerque toma argumentos por palabra clavename,descriptioneinput_schemay añade la función envuelta aregistered_toolsen__init__.py.
Bloque B — conjugate¶
En src/miniagent/tools/conjugate.py:
-
@register(name="conjugate", description="Return the conjugated form of an English verb.", input_schema={...})sobre una función: - Valida los args contra los enums §A13; lanza
ToolErrorsi están fuera de alcance. - Busca la forma en
data/processed/conjugation_table.json(o impórtala como dict Python). - Devuelve la cadena conjugada. P. ej.
conjugate("eat", "past_simple", "3sg")devuelve"ate". - Testea exhaustivamente: 20 verbos × 5 tiempos × 3 personas = 300 combinaciones. Todas deben hacer round-trip.
Bloque C — lookup_irregular_verb¶
En src/miniagent/tools/lookup_irregular_verb.py:
- Firma:
lookup_irregular_verb(verb: str) -> dict. - Devuelve
{"infinitive": ..., "past_simple": ..., "past_participle": ..., "is_irregular": true}para los 8 verbos irregulares (be, have, do, go, come, see, eat, write). - Para un verbo regular (uno de los 12), devuelve
{"is_irregular": false}— útil para que el agente pueda preguntar "¿es este irregular?" antes de comprometerse con una ruta de lookup. - Para un verbo fuera de alcance, lanza
ToolError.
Bloque D — lookup_spanish¶
En src/miniagent/tools/lookup_spanish.py:
- Firma:
lookup_spanish(english_form: str) -> str. -
english_formes la forma conjugada (p. ej.,"ate", no"eat"). - Devuelve la traducción canónica al español (español peninsular, forma tú, pretérito perfecto simple — ver
PHASE_31_PLAN.md§5 pitfall 6). - Para una forma fuera de alcance, lanza
ToolError.
Bloque E — check_subject_verb_agreement¶
En src/miniagent/tools/check_subject_verb_agreement.py:
- Firma:
check_subject_verb_agreement(subject: str, verb_form: str) -> dict. -
subjectes un pronombre:"I","you","he","she","it". (Los pronombres en plural están fuera del alcance §A13; devuelve unToolError.) -
verb_formes una forma inglesa conjugada. - Devuelve
{"agrees": bool, "expected_form": str | None}.expected_formse rellena cuandoagrees=false, nombrando la forma conjugada que sí concordaría.
Ejemplo: check_subject_verb_agreement("he", "go") devuelve {"agrees": false, "expected_form": "goes"}. check_subject_verb_agreement("he", "goes") devuelve {"agrees": true, "expected_form": null}.
Bloque F — tests¶
En tests/test_miniagent_tools.py:
-
test_conjugate_round_trip— 300 casos, todos coinciden con la tabla de verdad. -
test_conjugate_out_of_scope_raises—conjugate("run", "past_simple", "3sg")lanzaToolError. -
test_lookup_irregular_verb_returns_principal_parts— los 8 irregulares presentes, con past_simple y past_participle correctos. -
test_lookup_irregular_verb_marks_regulars—lookup_irregular_verb("work")devuelve{"is_irregular": false}. -
test_lookup_spanish_canonical—lookup_spanish("ate")devuelve"comió"(o lo que sea que especifique la tabla de verdad para 3sg past). -
test_check_agreement_pos— casos que concuerdan devuelvenagrees=true. -
test_check_agreement_neg_proposes_fix— casos que no concuerdan devuelvenagrees=falsecon elexpected_formcorrecto. -
test_check_agreement_plural_pronoun_out_of_scope—subject="we"lanzaToolError.
Bloque G — smoke demo¶
En experiments/31-typed-tools/demo.py:
- Importa
registered_toolsdesdesrc.miniagent.tools. - Imprime
nameydescriptionde cada tool. - Llama a cada tool con un input canónico; imprime el resultado.
- Escribe
results.jsoncon{tools_registered, smoke_test_pass}.
Restricciones¶
- Sin MCP todavía. Este lab es Python puro. El lab 01 introduce la capa de protocolo.
- La tabla de verdad es el contrato. La Fase 12 produjo los datos; las tools leen de ahí. No codifiques a mano la rejilla de conjugación dentro de las funciones de tool — eso permitiría que se desviara del corpus.
- Sin requisito de
pydantic. Si Borja quiere añadirlo para validación de argumentos, vale; si no, la validación condictde stdlib es suficiente. - Sin efectos secundarios de I/O. Las tools leen constantes y computan. No escriben ficheros, no van a la red, no llaman a servicios externos.
Condiciones de parada¶
Hecho cuando:
- Todos los tests del Bloque F pasan.
demo.pyimprime un transcript limpio y escriberesults.json.- El
input_schemade cada tool valida conjsonschema.Draft7Validator(schema).check_schema()(sanity-check de que el schema está bien formado).
Pitfalls¶
- Codificado a mano vs dirigido por tabla. Es fácil empezar a tipear la rejilla de conjugación dentro de
conjugate. Resiste; tira de la tabla de verdad. - Variantes de traducción al español. Elige una forma canónica por forma inglesa y documenta la elección. Las variantes (vos vs tú, peninsular vs latinoamericano) son no-features explícitas.
- Normalización de pronombres. "He" vs "he" vs "He.". Las tools deben pasar a minúsculas + quitar puntuación antes de comparar.
is_irregular: falseno es un error.lookup_irregular_verb("work")es una llamada exitosa que devuelve una respuesta útil — no una excepción.expected_formigual anullcuando concuerda. No devuelvas string vacío; devuelveNone. Distingue "no hace falta arreglo" de "el arreglo es el string vacío".
Cuándo consultar solutions/¶
Tras que todos los tests del Bloque F pasen. La solución en solutions/00-typed-tools-ref.md (escrita en la apertura de la fase) revisará las formas de los schemas; diferencias menores están bien pero el mapeo test-tabla-de-verdad debe coincidir.
Siguiente lab: lab/01-mcp-server.md.