# Known Issues — Errores reales con su fix Cada item acá fue pagado en sangre por Cotemar o Dun. Cuando te toque debuggear, leé primero, googleá después. --- ## I-001 — `recursion_limit reached` (langgraph) **Síntoma:** después de 2-3 tool calls el run muere con `GraphRecursionError`. **Causa:** WxO usa langgraph internamente con `recursion_limit=30` hardcoded (no configurable vía YAML ni API). Cada turno ReAct quema ~10 frames. **Fix:** Si tu flujo es lineal y conocido, **patrón meta-tool**: colapsá N tools en una sola `run_full_case(id)` que el backend orquesta internamente. El agente solo invoca esa tool. ```python # Antes: agent llama 5 tools en orden @tool def get_company(id): ... @tool def search_credits(id): ... @tool def build_profile(id): ... @tool def package_zip(id): ... @tool def upload(id): ... # Después: agent llama 1 meta-tool @tool def run_full_case(case_id): # Backend orquesta los 5 pasos internamente # cada uno emite write_audit(...) return {"package_url": "...", "audit_url": "..."} ``` **Origen:** Dun commit `895f5ee feat(orchestrate): consolidar 11 tools → run_full_case`. --- ## I-002 — Llama 3.3 70B printea tool calls como texto **Síntoma:** después del turno ~3, el agente "responde" con texto que literalmente dice: ``` Tool call: reset_password(username="juan.perez@cotemar.com") ``` en lugar de invocar la tool. **Causa:** Drift del modelo Llama 3.3 70B con tool calling. Documentado por IBM, mitigación recomendada: cambiar de modelo. **Fix:** 1. **Cambiar `llm:` a `groq/openai/gpt-oss-120b`** en el YAML del agente. 2. Agregar **REGLA #0** explícita en el prompt: > "NUNCA escribas la tool call como texto. Usá el protocolo de tool_calls." **Origen:** Dun commit `84be316`. --- ## I-003 — Pydantic 422 "value is not a valid integer" **Síntoma:** Una tool falla con `ValidationError: value is not a valid integer` aunque vos jurás que mandás un int. **Causa:** El LLM stringifica todo. Manda `"95727067"` cuando el schema es `int`. Pydantic v2 strict mode rechaza. **Fix:** Coerción explícita en el schema: ```python from pydantic import BaseModel, field_validator def _coerce_int(v): if isinstance(v, str) and v.strip().isdigit(): return int(v) return v def _coerce_list(v): if isinstance(v, str): import json try: return json.loads(v) except: return [v] return v class ResetPasswordInput(BaseModel): user_id: int groups: list[str] _coerce_user_id = field_validator("user_id", mode="before")(_coerce_int) _coerce_groups = field_validator("groups", mode="before")(_coerce_list) ``` El template trae estos helpers en [`wxo/tools/python/_coercion_helpers.py`](../wxo/tools/python/_coercion_helpers.py). **Origen:** Dun commit `3cdf3bf`. --- ## I-004 — `kid not found` al `agents deploy --env live` **Síntoma:** import del agente sale OK al draft, pero `deploy --env live` falla con `kid not found`. **Causa:** Las conexiones que el agente usa solo existen en el env `draft`. La promoción a `live` requiere que las connections existan también en `live`. **Fix:** Configurar connection en **ambos** envs: ```bash for ENV in draft live; do orchestrate connections configure -a mi_app --env $ENV --type team --kind key_value orchestrate connections set-credentials -a mi_app --env $ENV -e "BASE_URL=..." done ``` El `deploy-wxo.sh` del template ya lo hace. **Origen:** Cotemar (debug session 2026-05-13). --- ## I-005 — OpenAPI import: "No description provided" **Síntoma:** `orchestrate tools import -k openapi` falla con `No description provided for operation X`. **Causa:** ADK exige `description` por operación. FastAPI genera solo `summary` cuando la función no tiene docstring. **Fix:** Al exponer el spec, forzar el fallback: ```python # En tu endpoint /orchestrate-tools-spec.json for path_item in spec["paths"].values(): for op in path_item.values(): if isinstance(op, dict) and "responses" in op: op["description"] = op.get("description") or op.get("summary") or "..." ``` **Origen:** Dun `backend/app/api/v1/spec.py:60-66`. --- ## I-006 — OpenAPI security no se hereda **Síntoma:** Spec tiene `security:` global, pero ADK importa los tools sin auth. **Causa:** ADK no respeta `security` global. Requiere per-operation. **Fix:** Re-declarar en cada op: ```python for path_item in spec["paths"].values(): for op in path_item.values(): if isinstance(op, dict) and "responses" in op: op["security"] = spec.get("security", []) ``` **Origen:** Dun commit `1bc04cf`. --- ## I-007 — Embed widget queda en "Cargando agente..." **Síntoma:** Tu landing page con `