[{"data":1,"prerenderedAt":5474},["ShallowReactive",2],{"navigation":3,"\u002Fes\u002Farticles_index":177,"articles-index:\u002Fes\u002Farticles":196},[4,62],{"title":5,"path":6,"stem":7,"children":8},"About","\u002Fen","en\u002F1.index",[9,10,56],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13,"children":14},"Blog","\u002Fen\u002Farticles","en\u002F2.articles",[15],{"title":16,"path":17,"stem":18,"children":19,"page":33},"2026","\u002Fen\u002Farticles\u002F2026","en\u002Farticles\u002F2026",[20,34,47],{"title":21,"path":22,"stem":23,"children":24,"page":33},"April","\u002Fen\u002Farticles\u002F2026\u002Fapril","en\u002Farticles\u002F2026\u002Fapril",[25,29],{"title":26,"path":27,"stem":28},"Improving My App's Vibes with DESIGN.md","\u002Fen\u002Farticles\u002F2026\u002Fapril\u002Fexploring-llm-ui","en\u002Farticles\u002F2026\u002Fapril\u002Fexploring-llm-ui",{"title":30,"path":31,"stem":32},"How I Made My Fork Bilingual and Published It Right","\u002Fen\u002Farticles\u002F2026\u002Fapril\u002Fhow-i-made-my-fork-bilingual-and-published-it-right","en\u002Farticles\u002F2026\u002Fapril\u002Fhow-i-made-my-fork-bilingual-and-published-it-right",false,{"title":35,"path":36,"stem":37,"children":38,"page":33},"July","\u002Fen\u002Farticles\u002F2026\u002Fjuly","en\u002Farticles\u002F2026\u002Fjuly",[39,43],{"title":40,"path":41,"stem":42},"From Idea to MS Teams: Deploying an Agent","\u002Fen\u002Farticles\u002F2026\u002Fjuly\u002Ffrom-idea-to-ms-teams-agent","en\u002Farticles\u002F2026\u002Fjuly\u002Ffrom-idea-to-ms-teams-agent",{"title":44,"path":45,"stem":46},"Legally Spying on Your Competition is Possible","\u002Fen\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals","en\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals",{"title":48,"path":49,"stem":50,"children":51,"page":33},"May","\u002Fen\u002Farticles\u002F2026\u002Fmay","en\u002Farticles\u002F2026\u002Fmay",[52],{"title":53,"path":54,"stem":55},"Building an Agent's Personality Around the Customer Journey","\u002Fen\u002Farticles\u002F2026\u002Fmay\u002Fbuilding-agents-with-personality","en\u002Farticles\u002F2026\u002Fmay\u002Fbuilding-agents-with-personality",{"title":57,"path":58,"stem":59,"children":60},"Index","\u002Fen\u002Farticles_index","en\u002F4.articles_index",[61],{"title":57,"path":58,"stem":59},{"title":63,"path":64,"stem":65,"children":66},"Acerca De","\u002Fes","es\u002F1.index",[67,68,153,171],{"title":63,"path":64,"stem":65},{"title":11,"path":69,"stem":70,"children":71},"\u002Fes\u002Farticles","es\u002F2.articles",[72,95,117],{"title":73,"path":74,"stem":75,"children":76,"page":33},"2024","\u002Fes\u002Farticles\u002F2024","es\u002Farticles\u002F2024",[77,86],{"title":78,"path":79,"stem":80,"children":81,"page":33},"Diciembre","\u002Fes\u002Farticles\u002F2024\u002Fdiciembre","es\u002Farticles\u002F2024\u002Fdiciembre",[82],{"title":83,"path":84,"stem":85},"Diciembre es un mes más","\u002Fes\u002Farticles\u002F2024\u002Fdiciembre\u002Fhaikus","es\u002Farticles\u002F2024\u002Fdiciembre\u002Fhaikus",{"title":87,"path":88,"stem":89,"children":90,"page":33},"Octubre","\u002Fes\u002Farticles\u002F2024\u002Foctubre","es\u002Farticles\u002F2024\u002Foctubre",[91],{"title":92,"path":93,"stem":94},"Viaje de regreso","\u002Fes\u002Farticles\u002F2024\u002Foctubre\u002Fhaikus","es\u002Farticles\u002F2024\u002Foctubre\u002Fhaikus",{"title":96,"path":97,"stem":98,"children":99,"page":33},"2025","\u002Fes\u002Farticles\u002F2025","es\u002Farticles\u002F2025",[100,109],{"title":101,"path":102,"stem":103,"children":104,"page":33},"Agosto","\u002Fes\u002Farticles\u002F2025\u002Fagosto","es\u002Farticles\u002F2025\u002Fagosto",[105],{"title":106,"path":107,"stem":108},"Hola Mundo","\u002Fes\u002Farticles\u002F2025\u002Fagosto\u002Fholamundo","es\u002Farticles\u002F2025\u002Fagosto\u002Fholamundo",{"title":87,"path":110,"stem":111,"children":112,"page":33},"\u002Fes\u002Farticles\u002F2025\u002Foctubre","es\u002Farticles\u002F2025\u002Foctubre",[113],{"title":114,"path":115,"stem":116},"El Antipatrón de la Red Veloz","\u002Fes\u002Farticles\u002F2025\u002Foctubre\u002Flatencia","es\u002Farticles\u002F2025\u002Foctubre\u002Flatencia",{"title":16,"path":118,"stem":119,"children":120,"page":33},"\u002Fes\u002Farticles\u002F2026","es\u002Farticles\u002F2026",[121,133,145],{"title":21,"path":122,"stem":123,"children":124,"page":33},"\u002Fes\u002Farticles\u002F2026\u002Fapril","es\u002Farticles\u002F2026\u002Fapril",[125,129],{"title":126,"path":127,"stem":128},"Mejorando las VIBES de mi aplicación con DESIGN.md","\u002Fes\u002Farticles\u002F2026\u002Fapril\u002Fexploring-llm-ui","es\u002Farticles\u002F2026\u002Fapril\u002Fexploring-llm-ui",{"title":130,"path":131,"stem":132},"Cómo volví mi fork multilenguaje y lo publiqué bien","\u002Fes\u002Farticles\u002F2026\u002Fapril\u002Fhow-i-made-my-fork-bilingual-and-published-it-right","es\u002Farticles\u002F2026\u002Fapril\u002Fhow-i-made-my-fork-bilingual-and-published-it-right",{"title":35,"path":134,"stem":135,"children":136,"page":33},"\u002Fes\u002Farticles\u002F2026\u002Fjuly","es\u002Farticles\u002F2026\u002Fjuly",[137,141],{"title":138,"path":139,"stem":140},"De Idea a Ms Teams: Desplegando un Agente","\u002Fes\u002Farticles\u002F2026\u002Fjuly\u002Ffrom-idea-to-ms-teams-agent","es\u002Farticles\u002F2026\u002Fjuly\u002Ffrom-idea-to-ms-teams-agent",{"title":142,"path":143,"stem":144},"Espiar a Tu Competencia de Manera Legal es Posible","\u002Fes\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals","es\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals",{"title":48,"path":146,"stem":147,"children":148,"page":33},"\u002Fes\u002Farticles\u002F2026\u002Fmay","es\u002Farticles\u002F2026\u002Fmay",[149],{"title":150,"path":151,"stem":152},"Construyendo la personalidad de un agente en base a la travesía del cliente","\u002Fes\u002Farticles\u002F2026\u002Fmay\u002Fbuilding-agents-with-personality","es\u002Farticles\u002F2026\u002Fmay\u002Fbuilding-agents-with-personality",{"title":154,"path":155,"stem":156,"children":157},"Galería","\u002Fes\u002Fgallery","es\u002F3.gallery",[158],{"title":96,"path":159,"stem":160,"children":161,"page":33},"\u002Fes\u002Fgallery\u002F2025","es\u002Fgallery\u002F2025",[162],{"title":163,"path":164,"stem":165,"children":166,"page":33},"Septiembre","\u002Fes\u002Fgallery\u002F2025\u002Fseptiembre","es\u002Fgallery\u002F2025\u002Fseptiembre",[167],{"title":168,"path":169,"stem":170},"Cielo de Oyón","\u002Fes\u002Fgallery\u002F2025\u002Fseptiembre\u002Fholamundo","es\u002Fgallery\u002F2025\u002Fseptiembre\u002Fholamundo",{"title":172,"path":173,"stem":174,"children":175},"Lista","\u002Fes\u002Farticles_index","es\u002F4.articles_index",[176],{"title":172,"path":173,"stem":174},{"id":178,"title":172,"author":179,"badges":179,"body":180,"canonical":179,"cover":179,"date":179,"description":187,"extension":190,"layout":191,"meta":192,"navigation":193,"path":173,"seo":194,"stem":174,"__hash__":195},"content\u002Fes\u002F4.articles_index.md",null,{"type":181,"value":182,"toc":186},"minimark",[183],[184,185],"articles-index",{},{"title":187,"searchDepth":188,"depth":188,"links":189},"",2,[],"md","default",{},true,{"title":172,"description":187},"PeIDRPCGKX-qupTO00y6YZB6Rj9JxGIF3tPPgwOwGeA",[197,810,3316,4727,4865,5199,5339,5373,5436],{"id":198,"title":142,"author":199,"badges":179,"body":203,"canonical":179,"cover":796,"date":797,"description":798,"extension":190,"layout":799,"meta":800,"navigation":193,"path":143,"seo":806,"stem":144,"__hash__":809},"content\u002Fes\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals.md",{"name":200,"url":201,"avatarUrl":202},"Ever Burga","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Feverburga\u002F","https:\u002F\u002Fwww.linkedin.com\u002F",{"type":181,"value":204,"toc":780},[205,209,226,229,232,235,238,248,257,262,267,270,273,276,279,287,290,294,297,308,311,314,318,321,324,328,338,341,345,354,357,360,363,366,370,373,377,380,393,402,407,473,484,534,549,553,556,564,567,570,574,711,716,720,755,766,769,773,776],[206,207,142],"h1",{"id":208},"espiar-a-tu-competencia-de-manera-legal-es-posible",[210,211,214],"div",{"className":212},[213],"hero-breakout",[210,215,218],{"className":216},[217],"hero-breakout-inner",[219,220,221],"p",{},[222,223],"img",{"alt":224,"src":225},"Diagrama del flujo de rastreo de la competencia con datos abiertos","\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals-hero.svg",[219,227,228],{},"¿Cómo se obtiene datos de usuario de páginas que te interesa monitorear?",[219,230,231],{},"Usando datos públicos de Google!",[219,233,234],{},"No es necesario un scraper o suscripciones costosas a wappalyzer.",[219,236,237],{},"Solo necesitas ",[239,240,241,245],"ul",{},[242,243,244],"li",{},"La base de datos en bq y api de crux.",[242,246,247],{},"La base de datos de http archive en bq.",[219,249,250],{},[251,252,256],"a",{"href":253,"rel":254},"https:\u002F\u002Ftheuxreport.kekeros.com",[255],"nofollow","theuxreport",[258,259,261],"h2",{"id":260},"decisiones-de-arquitectura","Decisiones de Arquitectura",[263,264,266],"h3",{"id":265},"primero-veamos-la-naturaleza-de-las-fuentes-de-datos","Primero veamos la naturaleza de las fuentes de datos",[219,268,269],{},"Las BD de crux y http archive se actualizan mensualmente. Crux tiene un retraso de 2 meses, mientras que http archive de solo 1 mes. Esta diferencia tiene impacto para el análisis de datos. Por eso conviene etiquetar el mes de provenance de cada dato que ingrese a nuestro data lake. ",[219,271,272],{},"Por otro lado, para el usuario final que solo quiere ver reportes, la diferencia de 1 mes no importa mucho. Incluso se podría interpretar como un retraso de procesamiento o algun desfase insignificante entre los gráficos históricos. ",[219,274,275],{},"Ahora, si nos enfocamos en el volumen de datos, cada base de datos utiliza como identificador un campo llamado origin, que podemos interpretar como el dominio web del que se sirve el contenido y las aplicaciones. ",[219,277,278],{},"Cada origin tiene decenas de columnas en total. Pero al fin de al cabo, un tamaño fijo de datos. Esto significa que el volumen de datos crece, dados los parámetros",[239,280,281,284],{},[242,282,283],{},"N: número de origins a analizar",[242,285,286],{},"T: cantidad de unidades temporales a analizar,",[219,288,289],{},"... con complejidad O(NT). Para mi lista inicial de dominios peruanos registré 20mil dominios y mi objetivo es mantener una ventana de 24 semanas en el reporte. Dudo que en el futuro supere los 100mil dominios, así que tenemos un volumen modesto de datos que se puede procesar en un solo nodo, o mi computadora.",[263,291,293],{"id":292},"requisitos-y-restricciones","Requisitos y restricciones",[219,295,296],{},"Entre otros requisitos más específicos,",[239,298,299,302,305],{},[242,300,301],{},"Quiero almacenar los datos históricos y enrichment en un formato de bajo costo de almacenamiento pero con alta garantía de integridad de datos.",[242,303,304],{},"Mi página de reportes debe tener alta disponibilidad y presentar una experiencia de usuario fluida.",[242,306,307],{},"Quiero mantener costos de mantenimiento mínimos.",[219,309,310],{},"AWS S3 + Athena, GCP BigQuery Iceberg Catalog... hay muchas soluciones en el mercado. Esta vez decidí usar Cloudfare R2 Data Catalog, con una generosa cuota de 10GB de almacenamiento gratis y alto número de lecturas y escrituras. ",[219,312,313],{},"En cuanto a la página, Astro es mi opción preferida en estos casos. Y la CDN será CloudFare para mantener sencillez de administración.",[258,315,317],{"id":316},"transformación-de-datos","Transformación De Datos",[219,319,320],{},"Las etapas de extracción, filtro y enrichment son sencillas. ",[219,322,323],{},"Sin embargo, http archive no entrega categorías tecnológicas normalizadas. Como usa el motor de firmas de wappalyzer, simplemente entrega categorías de lo que sea que detecte. Puedes tener React.js y Next.js a la vez, incluso cuando sabemos que Next.js es un meta-framework de React y no existe sin este.",[263,325,327],{"id":326},"etapa-1-remapeo-a-macrocategorías","Etapa 1: Remapeo a Macrocategorías",[219,329,330,334],{},[222,331],{"alt":332,"src":333},"Diagrama del remapeo de categorías crudas a macrocategorías normalizadas","\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals-remapping.svg",[335,336,337],"em",{},"Remapeo de categorías crudas a macrocategorías normalizadas.",[219,339,340],{},"Origin_Technologies de R2 con una lista de categorías por tecnología. Después de agruparlas tenemos menos complejidad con la que trabajar. Pero es en esta etapa en la que hacemos el trabajo sucio.",[263,342,344],{"id":343},"etapa-2-limpiando-empates","Etapa 2: Limpiando empates.",[219,346,347,351],{},[222,348],{"alt":349,"src":350},"Diagrama del proceso LinearUntie para colapsar tecnologías atadas a una misma macrocategoría","\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals-linear-untie.svg",[335,352,353],{},"LinearUntie: colapsando tecnologías atadas a una misma macrocategoría.",[219,355,356],{},"Un origen puede tener varias tecnologías para la misma categoría. Esto es una consecuencia de lo que te conté antes. Puedes tener Next.js y Next App Router clasificados dentro de la misma categoría de Web Frameworks.",[219,358,359],{},"Para colapsar estos empates uso un ordenamiento lineal de las tecnologías de acuerdo a categoría. Si encuentro Nest.js y Express a la vez, Nest.js es la opción que agrupa ambos conceptos.",[219,361,362],{},"Una mejora directa a este modelo es realizar ordenamientos no solo por categoría, sino por categoría + framework. Pero esto requiere una tarea de relacionamiento costosa y de todas maneras hay excepciones que parten de la naturaleza con la que http archive genera los datos. ",[219,364,365],{},"Las excepciones menores o tecnologías mal categorizadas las voy agregando manualmente a una estructura en disco. Es un trabajo inevitable",[258,367,369],{"id":368},"ranking","Ranking",[219,371,372],{},"Una vez que ya tienes los conjuntos de datos normalizados el ranking se vuelve una tarea de estadística, y la página de reportes un proceso de diseño y UI.",[258,374,376],{"id":375},"the-ux-report","The UX Report",[219,378,379],{},"Si te interesa validar los resultados que ves en la web o alguna publicación, estos son los pasos.",[263,381,383,384,388,389,392],{"id":382},"cómo-reproducir-tu-severity-y-tu-score-con-la-api-pública-de-crux","Cómo reproducir tu ",[385,386,387],"strong",{},"severity"," y tu ",[385,390,391],{},"score"," con la API pública de CrUX",[219,394,395,396,401],{},"Lo que se muestra en la sección Core Web Vitals sale directo de la ",[251,397,400],{"href":398,"rel":399},"https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fcrux\u002Fapi",[255],"Chrome UX Report API"," de Google y que se usan en su ranking de SEO.",[403,404,406],"h4",{"id":405},"_1-pide-un-histograma-a-través-de-la-crux-api","1. Pide un histograma a través de la CrUX API",[408,409,413],"pre",{"className":410,"code":411,"language":412,"meta":187,"style":187},"language-bash shiki shiki-themes github-light github-dark","curl --request POST \\\n  'https:\u002F\u002Fchromeuxreport.googleapis.com\u002Fv1\u002Frecords:queryRecord?key=TU_API_KEY' \\\n  --header 'Accept: application\u002Fjson' \\\n  --header 'Content-Type: application\u002Fjson' \\\n  --data '{\"origin\":\"https:\u002F\u002Ftu-dominio.pe\"}'\n","bash",[414,415,416,436,443,454,464],"code",{"__ignoreMap":187},[417,418,421,425,429,433],"span",{"class":419,"line":420},"line",1,[417,422,424],{"class":423},"sScJk","curl",[417,426,428],{"class":427},"sj4cs"," --request",[417,430,432],{"class":431},"sZZnC"," POST",[417,434,435],{"class":427}," \\\n",[417,437,438,441],{"class":419,"line":188},[417,439,440],{"class":431},"  'https:\u002F\u002Fchromeuxreport.googleapis.com\u002Fv1\u002Frecords:queryRecord?key=TU_API_KEY'",[417,442,435],{"class":427},[417,444,446,449,452],{"class":419,"line":445},3,[417,447,448],{"class":427},"  --header",[417,450,451],{"class":431}," 'Accept: application\u002Fjson'",[417,453,435],{"class":427},[417,455,457,459,462],{"class":419,"line":456},4,[417,458,448],{"class":427},[417,460,461],{"class":431}," 'Content-Type: application\u002Fjson'",[417,463,435],{"class":427},[417,465,467,470],{"class":419,"line":466},5,[417,468,469],{"class":427},"  --data",[417,471,472],{"class":431}," '{\"origin\":\"https:\u002F\u002Ftu-dominio.pe\"}'\n",[219,474,475,476,479,480,483],{},"La respuesta trae, por cada métrica, un ",[385,477,478],{},"histogram"," de 3 bins: bueno \u002F necesita mejora \u002F malo — cada uno con una ",[385,481,482],{},"density"," (fracción real de visitas de usuarios reales en ese rango, no un promedio sintético):",[408,485,489],{"className":486,"code":487,"language":488,"meta":187,"style":187},"language-json shiki shiki-themes github-light github-dark","\"largest_contentful_paint\": {\n  \"histogram\": [\n    { \"start\": 0,    \"end\": 2500, \"density\": 0.82 },\n    { \"start\": 2500, \"end\": 4000, \"density\": 0.11 },\n    { \"start\": 4000,               \"density\": 0.07 }\n  ],\n  \"percentiles\": { \"p75\": 2380 }\n}\n","json",[414,490,491,496,501,506,511,516,522,528],{"__ignoreMap":187},[417,492,493],{"class":419,"line":420},[417,494,495],{},"\"largest_contentful_paint\": {\n",[417,497,498],{"class":419,"line":188},[417,499,500],{},"  \"histogram\": [\n",[417,502,503],{"class":419,"line":445},[417,504,505],{},"    { \"start\": 0,    \"end\": 2500, \"density\": 0.82 },\n",[417,507,508],{"class":419,"line":456},[417,509,510],{},"    { \"start\": 2500, \"end\": 4000, \"density\": 0.11 },\n",[417,512,513],{"class":419,"line":466},[417,514,515],{},"    { \"start\": 4000,               \"density\": 0.07 }\n",[417,517,519],{"class":419,"line":518},6,[417,520,521],{},"  ],\n",[417,523,525],{"class":419,"line":524},7,[417,526,527],{},"  \"percentiles\": { \"p75\": 2380 }\n",[417,529,531],{"class":419,"line":530},8,[417,532,533],{},"}\n",[219,535,536,537,540,541,544,545,548],{},"Las tres métricas que importan son ",[385,538,539],{},"largest_contentful_paint"," (LCP), ",[385,542,543],{},"cumulative_layout_shift"," (CLS) e ",[385,546,547],{},"interaction_to_next_paint"," (INP). Los core web vitals oficiales de Google.",[403,550,552],{"id":551},"_2-calcula-el-severity-de-cada-métrica","2. Calcula el severity de cada métrica",[219,554,555],{},"Por cada métrica, el severity es un promedio ponderado por la densidad real de cada banda:",[408,557,562],{"className":558,"code":560,"language":561},[559],"language-text","severity_métrica = poor × 1.0 + needs_improvement × 0.5 + good × 0.0\n","text",[414,563,560],{"__ignoreMap":187},[219,565,566],{},"Con el ejemplo de arriba: 0.07 × 1.0 + 0.11 × 0.5 + 0.82 × 0.0 = 0.125.",[219,568,569],{},"¿Por qué ponderado y no \"banda dominante\"? Porque un origen con 51% good \u002F 49% needs-improvement y otro con 99% good \u002F 1% needs-improvement son historias reales muy distintas",[403,571,573],{"id":572},"_3-promedia-las-tres-métricas","3. Promedia las tres métricas",[408,575,579],{"className":576,"code":577,"language":578,"meta":187,"style":187},"language-python shiki shiki-themes github-light github-dark","def metric_severity(good: float, ni: float, poor: float) -> float:\n    return poor * 1.0 + ni * 0.5 + good * 0.0\n\nseverity = (\n    metric_severity(*lcp_densities)\n    + metric_severity(*cls_densities)\n    + metric_severity(*inp_densities)\n) \u002F 3\n","python",[414,580,581,615,650,655,666,676,689,700],{"__ignoreMap":187},[417,582,583,587,590,594,597,600,602,605,607,610,612],{"class":419,"line":420},[417,584,586],{"class":585},"szBVR","def",[417,588,589],{"class":423}," metric_severity",[417,591,593],{"class":592},"sVt8B","(good: ",[417,595,596],{"class":427},"float",[417,598,599],{"class":592},", ni: ",[417,601,596],{"class":427},[417,603,604],{"class":592},", poor: ",[417,606,596],{"class":427},[417,608,609],{"class":592},") -> ",[417,611,596],{"class":427},[417,613,614],{"class":592},":\n",[417,616,617,620,623,626,629,632,635,637,640,642,645,647],{"class":419,"line":188},[417,618,619],{"class":585},"    return",[417,621,622],{"class":592}," poor ",[417,624,625],{"class":585},"*",[417,627,628],{"class":427}," 1.0",[417,630,631],{"class":585}," +",[417,633,634],{"class":592}," ni ",[417,636,625],{"class":585},[417,638,639],{"class":427}," 0.5",[417,641,631],{"class":585},[417,643,644],{"class":592}," good ",[417,646,625],{"class":585},[417,648,649],{"class":427}," 0.0\n",[417,651,652],{"class":419,"line":445},[417,653,654],{"emptyLinePlaceholder":193},"\n",[417,656,657,660,663],{"class":419,"line":456},[417,658,659],{"class":592},"severity ",[417,661,662],{"class":585},"=",[417,664,665],{"class":592}," (\n",[417,667,668,671,673],{"class":419,"line":466},[417,669,670],{"class":592},"    metric_severity(",[417,672,625],{"class":585},[417,674,675],{"class":592},"lcp_densities)\n",[417,677,678,681,684,686],{"class":419,"line":518},[417,679,680],{"class":585},"    +",[417,682,683],{"class":592}," metric_severity(",[417,685,625],{"class":585},[417,687,688],{"class":592},"cls_densities)\n",[417,690,691,693,695,697],{"class":419,"line":524},[417,692,680],{"class":585},[417,694,683],{"class":592},[417,696,625],{"class":585},[417,698,699],{"class":592},"inp_densities)\n",[417,701,702,705,708],{"class":419,"line":530},[417,703,704],{"class":592},") ",[417,706,707],{"class":585},"\u002F",[417,709,710],{"class":427}," 3\n",[219,712,713,715],{},[385,714,387],{}," queda entre 0 (perfecto) y 1 (el peor caso posible). Si a tu origen le falta alguna de las tres métricas en esta ventana (CrUX exige un mínimo de tráfico por métrica para publicarla) lo que hago es completar el dato con el promedio del cohorte de esa ventana de datos. En ese caso sí tendrías problemas para reproducir tu score completo, pero puedes usar un valor placeholder de 50% para llegar a un aproximado.",[403,717,719],{"id":718},"_4-tu-score","4. Tu score",[408,721,723],{"className":576,"code":722,"language":578,"meta":187,"style":187},"score = round((1 - severity) * 100)\n",[414,724,725],{"__ignoreMap":187},[417,726,727,730,732,735,738,741,744,747,749,752],{"class":419,"line":420},[417,728,729],{"class":592},"score ",[417,731,662],{"class":585},[417,733,734],{"class":427}," round",[417,736,737],{"class":592},"((",[417,739,740],{"class":427},"1",[417,742,743],{"class":585}," -",[417,745,746],{"class":592}," severity) ",[417,748,625],{"class":585},[417,750,751],{"class":427}," 100",[417,753,754],{"class":592},")\n",[219,756,757,758,761,762,765],{},"Con ",[385,759,760],{},"severity = 0.125",", el score es ",[385,763,764],{},"87\u002F100",". Este número es 100% reproducible por cualquiera con solo la API pública de Google.",[219,767,768],{},"Espero que te haya gustado el artículo. Recuerda que cada mes actualizo el reporte de páginas. Te veo en mis métricas de analytics pronto!",[258,770,772],{"id":771},"colaboración","Colaboración",[219,774,775],{},"Tengo planeado liberar de manera open source el proyecto cuando entre en una etapa estable. Si quieres apoyar con alguna lista de URLs que consideras necesarias o una métrica que te gustaría tener escríbeme a mis redes con gusto.",[777,778,779],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":187,"searchDepth":188,"depth":188,"links":781},[782,786,790,791,795],{"id":260,"depth":188,"text":261,"children":783},[784,785],{"id":265,"depth":445,"text":266},{"id":292,"depth":445,"text":293},{"id":316,"depth":188,"text":317,"children":787},[788,789],{"id":326,"depth":445,"text":327},{"id":343,"depth":445,"text":344},{"id":368,"depth":188,"text":369},{"id":375,"depth":188,"text":376,"children":792},[793],{"id":382,"depth":445,"text":794},"Cómo reproducir tu severity y tu score con la API pública de CrUX",{"id":771,"depth":188,"text":772},"\u002Farticles\u002F2026\u002Fjuly\u002Fspying-on-your-rivals-cover.svg","2026-07-20T10:00:00.000Z","Rastrea a tu competencia con datos abiertos es una tarea... no tan difícil.","article",{"head":801},{"meta":802},[803],{"name":804,"content":805},"keywords","crux, http archive, bigquery, análisis competitivo, tecnologías web, wappalyzer, cloudflare r2, data lake, seo, analítica web",{"title":807,"description":808},"Rastreando a Los Usuarios de Tu Competencia","Rastrear a tu competencia con datos públicos es sencillo.","DkNrom9ryCwwNayT6tT2LTiH9ZD-eFic0vvGfg1IkP0",{"id":811,"title":138,"author":812,"badges":179,"body":813,"canonical":179,"cover":3306,"date":3307,"description":3308,"extension":190,"layout":799,"meta":3309,"navigation":193,"path":139,"seo":3314,"stem":140,"__hash__":3315},"content\u002Fes\u002Farticles\u002F2026\u002Fjuly\u002Ffrom-idea-to-ms-teams-agent.md",{"name":200,"url":201},{"type":181,"value":814,"toc":3287},[815,818,831,834,837,841,847,855,859,862,879,882,886,889,892,901,911,921,924,928,931,940,943,946,950,956,2284,2292,2297,2340,2343,2347,2350,2358,2362,2366,2369,2378,2382,2385,2401,2404,2407,2411,2415,2423,2427,2481,2484,2488,2491,3243,3247,3284],[206,816,138],{"id":817},"de-idea-a-ms-teams-desplegando-un-agente",[219,819,820,824],{},[222,821],{"alt":822,"src":823,"title":822},"Flujo de desarrollo del Agents Toolkit","\u002Farticles\u002F2026\u002Fjuly\u002Fagent-toolkit-dev-flow.png",[335,825,826,827],{},"Tomado de ",[251,828,830],{"href":829},"#ref-1","[1]",[219,832,833],{},"A la fecha existe una creciente cantidad de servicios y vías de entrada para desplegar un agente en Ms Teams. Puede ser a través de Copilot, Microsoft 365 o con los servicios de AI Foundry.\nEn el fondo todos ellos usan las APIs de Azure Bot Services.",[219,835,836],{},"Si quieres máxima personalización, este tutorial te va a gustar.",[258,838,840],{"id":839},"prerrequisitos","Prerrequisitos.",[219,842,843,844,846],{},"Si tienes problemas con que tu administrador de Azure te otorgue permisos documentados en un artículo de un don nadie, este blog de Microsoft realiza pasos similares a los de estos artículos ",[251,845,830],{"href":829},".",[239,848,849,852],{},[242,850,851],{},"Rol de Application Developer en la suscripción de Azure donde estará asignado tu proyecto.",[242,853,854],{},"Licencia de MS Teams Corporativa. Como alternativa existe un programa de prueba de Microsoft 365 Dev que puedes probar, pero son 90 días y de todas maneras necesitas usar una suscripción activa de Azure.\nResulta redundante hacer todo el trabajo allí en lugar de aislar un grupo de usuarios en la consola de admin de 365 de tu organización.",[258,856,858],{"id":857},"contenido","Contenido",[219,860,861],{},"Lo que este tutorial cubre:",[239,863,864,867,870,873,876],{},[242,865,866],{},"Creación de la App en Azure Entra ID. Aquí se gestionan los permisos y es la cara visible de tu Agente para todo Microsoft en el mismo tenant.",[242,868,869],{},"Configuración de Azure Bot services. Esta es la API de integración para la suite de MS 365.",[242,871,872],{},"Integración con tu Agente propio, LangGraph self-hosted o lo que sea que hayas desarrollado. Aquí vemos cómo lo conectas con Azure Bot Services.",[242,874,875],{},"Publicación en Teams: Reglas de exclusión de usuarios, íconos, logos y versionamiento.",[242,877,878],{},"Detallitos de CX, D:",[219,880,881],{},"No vamos a ver la lógica del agente. Lo que te interesa, como a mí en su momento, es saber cómo lo despliego en mi suite corporativa.",[258,883,885],{"id":884},"entra-id","Entra ID",[219,887,888],{},"Azure a veces es una pesadilla. Veamos paso a paso.",[219,890,891],{},"Primero, crea una app con un nombre y un sufijo 'dev' o 'prd'. Necesitarás hacer esta distinción para poder segregar los usuarios más adelante.",[219,893,894,899],{},[222,895],{"alt":896,"src":897,"title":898},"Ingresa al servicio de Entra ID","\u002Farticles\u002F2026\u002Fjuly\u002Fentra-id-tuto.png","Ingresa al servicio",[335,900,898],{},[219,902,903,908],{},[222,904],{"alt":905,"src":906,"title":907},"Registro de una nueva app","\u002Farticles\u002F2026\u002Fjuly\u002Fapp-registration-add-new.png","Dale a crear",[335,909,910],{},"Dale a crear. Single tenant es suficiente para la mayoría de casos de uso.",[219,912,913,918],{},[222,914],{"alt":915,"src":916,"title":917},"Panel de registro de la app","\u002Farticles\u002F2026\u002Fjuly\u002Fapp-registration-panel.png","Apunta la App Id",[335,919,920],{},"Apunta la App Id.",[219,922,923],{},"Si necesitas que tu agente interactúe con servicios de Microsoft, la sección de API Permissions será tu amiga. En caso tu Agente no se encuentre en el ecosistema de Azure, una solución rápida es crear un certificado en la sección de Certificates y Secrets. En ese caso te apuntas el Secret que generes.",[258,925,927],{"id":926},"azure-bot-services","Azure Bot Services",[219,929,930],{},"Crea un Bot con la misma App Id que usaste para Entra Id. No estoy seguro de la razón de esto, pero cuando usaba la Id automática hubo problemas con la aparición del bot en la consola de Admin Microsoft 365.",[219,932,933,937],{},[222,934],{"alt":935,"src":936,"title":935},"Panel de configuración de Azure Bot Services","\u002Farticles\u002F2026\u002Fjuly\u002Fazure-bot-services-config-panel.png",[335,938,939],{},"Aquí los dos elementos más importantes tienen flechas.",[219,941,942],{},"El campo de URL endpoint es el endpoint del middleware que construirás a continuación.",[219,944,945],{},"La sección de 'prueba web' te permite probar que tu agente y tu middleware de integración efectivamente funcionan y responden correctamente.",[258,947,949],{"id":948},"integración","Integración",[951,952,953],"ol",{},[242,954,955],{},"Esto es una versión simplificada de un adaptador que me funciona.",[408,957,959],{"className":576,"code":958,"language":578,"meta":187,"style":187},"import os\nfrom dotenv import load_dotenv, find_dotenv\nload_dotenv(find_dotenv(\".prd.env\"))\n\nfrom botbuilder.integration.aiohttp import CloudAdapter, ConfigurationBotFrameworkAuthentication\n\nfrom src.ext.teams_incoming_adapter import BotInconmingEventsHandler\nfrom src.app.bot_service.service import BotService\nfrom src.ext.session_adapter import SessionStoreAdapter\nfrom src.app.session_watcher_service.service import SessionWatcher\n\nimport logging\n\n# Configure logging\nlogging.basicConfig(\n    level=logging.DEBUG,  # Set to DEBUG, INFO, WARNING, ERROR, or CRITICAL\n    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'\n)\n\nlogger = logging.getLogger(__name__)\n\nPORT = int(os.environ.get(\"SVC_LISTEN_PORT\", \"3978\"))\nAPP_ID = os.environ.get(\"MICROSOFT_APP_ID\", \"\")\nAPP_PASSWORD = os.environ.get(\"MICROSOFT_APP_PASSWORD\", \"\")\nAPP_TYPE = os.environ.get(\"MICROSOFT_APP_TYPE\", \"\")\nAPP_TENANTID = os.environ.get(\"MICROSOFT_APP_TENANT_ID\", \"\")\nMAX_IDLE_TIME = int(os.environ.get(\"SESSION_IDLE_LIMIT_SECS\"))  # secs\nALERT_TIME = int(os.environ.get(\"SESSION_IDLE_WARN_SECS\"))\n\nprint(f\"Configuration loaded. App ID: {APP_ID}, Port: {PORT}\")\nlogger.info(f\"✓ App ID: {APP_ID}\")\nlogger.info(f\"✓ App Type: {APP_TYPE}\")\nlogger.info(f\"✓ Tenant ID: {APP_TENANTID}\")\nlogger.info(f\"✓ Password length: {len(APP_PASSWORD) if APP_PASSWORD else 0}\")\n\nif not APP_PASSWORD:\n    logger.error(\"❌ MICROSOFT_APP_PASSWORD is EMPTY!\")\nif not APP_ID:\n    logger.error(\"❌ MICROSOFT_APP_ID is EMPTY!\")\n\nclass BotConfig:\n    PORT = PORT\n    APP_TYPE = APP_TYPE\n    APP_ID = APP_ID\n    APP_PASSWORD = APP_PASSWORD\n    APP_TENANTID = APP_TENANTID\n\nconfig = BotConfig()\n# Cloud Adapter is a bot\nBOT_CLOUD_ADAPTER = CloudAdapter(ConfigurationBotFrameworkAuthentication(config, logger=logger))\n\n\nreturn_last_message_only = os.environ.get(\"BOT_BACKEND_LAST_MSG_ONLY\", \"true\").strip().lower() in (\"1\", \"true\", \"yes\", \"on\")\nquery_url = os.environ.get(\"BOT_BACKEND_ENDPOINT\")\nif not query_url:\n    raise ValueError(\"BOT_BACKEND_ENDPOINT is required\")\n\nchatbot_adapter = AgentEngineADKAdapter(\n    query_url=query_url,\n    timeout_seconds=float(os.environ.get(\"BOT_BACKEND_TIMEOUT_SECS\", \"60\")),\n    return_last_message_only=return_last_message_only,\n    class_method=os.environ.get(\"BOT_BACKEND_CLASS_METHOD\", \"async_stream_query\"),\n)\nlogger.info(\"Agent Engine REST adapter initialized as primary chatbot adapter\")\n\n# Plug in whatever session store you use (a database, cache, etc.)\ndata_store = SessionStoreAdapter(\n    connection_string=os.environ.get(\"DATASTORE_DSN\"),\n)\nlogger.info(\"Session store adapter initialized\")\n\n# Plug in whatever feedback storage you use\nfeedback_repository = FeedbackRepository(\n    connection_string=os.environ.get(\"FEEDBACK_DSN\"),\n)\n\nfeedback_handler = DefaultFeedbackHandler(feedback_repository)\n\nbot_service = BotService(\n    chatbot_adapter=chatbot_adapter,\n    data_store=data_store,\n    fallback_adapter=None,\n    bot_adapter=BOT_CLOUD_ADAPTER,\n    app_id=APP_ID,\n    feedback_handler=feedback_handler,\n    alert_idle_seconds=ALERT_TIME,\n    close_idle_seconds=MAX_IDLE_TIME,\n)\n\nincoming_events_handler = BotInconmingEventsHandler(APP_ID, APP_PASSWORD, bot_service)\n\nhttp_adapter = HTTPAdapter(BOT_CLOUD_ADAPTER, incoming_events_handler)\napp = http_adapter.get_app()\n\n# Start session watcher if data store is available\nif data_store is not None:\n    try:\n        watcher = SessionWatcher(data_store, bot_service, alert_idle_seconds=ALERT_TIME,\n                                 close_idle_seconds=MAX_IDLE_TIME)\n        watcher.start()\n    except Exception as e:\n        print(f\"Warning: could not start session watcher: {e}\")\n\nif __name__ == \"__main__\":\n    from aiohttp import web\n    try:\n        web.run_app(app, host=\"0.0.0.0\", port=PORT)\n    except Exception as error:\n        raise error\n",[414,960,961,969,982,993,997,1009,1013,1025,1037,1050,1063,1068,1076,1081,1088,1094,1115,1148,1153,1158,1174,1179,1205,1226,1245,1264,1283,1304,1321,1326,1355,1372,1389,1406,1441,1446,1458,1469,1481,1491,1496,1507,1518,1529,1540,1551,1562,1567,1578,1584,1603,1608,1613,1659,1674,1684,1700,1705,1716,1727,1750,1761,1783,1788,1798,1803,1809,1820,1835,1840,1850,1855,1861,1872,1886,1891,1896,1907,1912,1923,1934,1945,1959,1971,1983,1994,2006,2018,2023,2028,2048,2053,2069,2080,2085,2091,2109,2117,2137,2149,2155,2170,2196,2201,2217,2231,2238,2263,2275],{"__ignoreMap":187},[417,962,963,966],{"class":419,"line":420},[417,964,965],{"class":585},"import",[417,967,968],{"class":592}," os\n",[417,970,971,974,977,979],{"class":419,"line":188},[417,972,973],{"class":585},"from",[417,975,976],{"class":592}," dotenv ",[417,978,965],{"class":585},[417,980,981],{"class":592}," load_dotenv, find_dotenv\n",[417,983,984,987,990],{"class":419,"line":445},[417,985,986],{"class":592},"load_dotenv(find_dotenv(",[417,988,989],{"class":431},"\".prd.env\"",[417,991,992],{"class":592},"))\n",[417,994,995],{"class":419,"line":456},[417,996,654],{"emptyLinePlaceholder":193},[417,998,999,1001,1004,1006],{"class":419,"line":466},[417,1000,973],{"class":585},[417,1002,1003],{"class":592}," botbuilder.integration.aiohttp ",[417,1005,965],{"class":585},[417,1007,1008],{"class":592}," CloudAdapter, ConfigurationBotFrameworkAuthentication\n",[417,1010,1011],{"class":419,"line":518},[417,1012,654],{"emptyLinePlaceholder":193},[417,1014,1015,1017,1020,1022],{"class":419,"line":524},[417,1016,973],{"class":585},[417,1018,1019],{"class":592}," src.ext.teams_incoming_adapter ",[417,1021,965],{"class":585},[417,1023,1024],{"class":592}," BotInconmingEventsHandler\n",[417,1026,1027,1029,1032,1034],{"class":419,"line":530},[417,1028,973],{"class":585},[417,1030,1031],{"class":592}," src.app.bot_service.service ",[417,1033,965],{"class":585},[417,1035,1036],{"class":592}," BotService\n",[417,1038,1040,1042,1045,1047],{"class":419,"line":1039},9,[417,1041,973],{"class":585},[417,1043,1044],{"class":592}," src.ext.session_adapter ",[417,1046,965],{"class":585},[417,1048,1049],{"class":592}," SessionStoreAdapter\n",[417,1051,1053,1055,1058,1060],{"class":419,"line":1052},10,[417,1054,973],{"class":585},[417,1056,1057],{"class":592}," src.app.session_watcher_service.service ",[417,1059,965],{"class":585},[417,1061,1062],{"class":592}," SessionWatcher\n",[417,1064,1066],{"class":419,"line":1065},11,[417,1067,654],{"emptyLinePlaceholder":193},[417,1069,1071,1073],{"class":419,"line":1070},12,[417,1072,965],{"class":585},[417,1074,1075],{"class":592}," logging\n",[417,1077,1079],{"class":419,"line":1078},13,[417,1080,654],{"emptyLinePlaceholder":193},[417,1082,1084],{"class":419,"line":1083},14,[417,1085,1087],{"class":1086},"sJ8bj","# Configure logging\n",[417,1089,1091],{"class":419,"line":1090},15,[417,1092,1093],{"class":592},"logging.basicConfig(\n",[417,1095,1097,1101,1103,1106,1109,1112],{"class":419,"line":1096},16,[417,1098,1100],{"class":1099},"s4XuR","    level",[417,1102,662],{"class":585},[417,1104,1105],{"class":592},"logging.",[417,1107,1108],{"class":427},"DEBUG",[417,1110,1111],{"class":592},",  ",[417,1113,1114],{"class":1086},"# Set to DEBUG, INFO, WARNING, ERROR, or CRITICAL\n",[417,1116,1118,1121,1123,1126,1129,1132,1135,1137,1140,1142,1145],{"class":419,"line":1117},17,[417,1119,1120],{"class":1099},"    format",[417,1122,662],{"class":585},[417,1124,1125],{"class":431},"'",[417,1127,1128],{"class":427},"%(asctime)s",[417,1130,1131],{"class":431}," - ",[417,1133,1134],{"class":427},"%(name)s",[417,1136,1131],{"class":431},[417,1138,1139],{"class":427},"%(levelname)s",[417,1141,1131],{"class":431},[417,1143,1144],{"class":427},"%(message)s",[417,1146,1147],{"class":431},"'\n",[417,1149,1151],{"class":419,"line":1150},18,[417,1152,754],{"class":592},[417,1154,1156],{"class":419,"line":1155},19,[417,1157,654],{"emptyLinePlaceholder":193},[417,1159,1161,1164,1166,1169,1172],{"class":419,"line":1160},20,[417,1162,1163],{"class":592},"logger ",[417,1165,662],{"class":585},[417,1167,1168],{"class":592}," logging.getLogger(",[417,1170,1171],{"class":427},"__name__",[417,1173,754],{"class":592},[417,1175,1177],{"class":419,"line":1176},21,[417,1178,654],{"emptyLinePlaceholder":193},[417,1180,1182,1185,1188,1191,1194,1197,1200,1203],{"class":419,"line":1181},22,[417,1183,1184],{"class":427},"PORT",[417,1186,1187],{"class":585}," =",[417,1189,1190],{"class":427}," int",[417,1192,1193],{"class":592},"(os.environ.get(",[417,1195,1196],{"class":431},"\"SVC_LISTEN_PORT\"",[417,1198,1199],{"class":592},", ",[417,1201,1202],{"class":431},"\"3978\"",[417,1204,992],{"class":592},[417,1206,1208,1211,1213,1216,1219,1221,1224],{"class":419,"line":1207},23,[417,1209,1210],{"class":427},"APP_ID",[417,1212,1187],{"class":585},[417,1214,1215],{"class":592}," os.environ.get(",[417,1217,1218],{"class":431},"\"MICROSOFT_APP_ID\"",[417,1220,1199],{"class":592},[417,1222,1223],{"class":431},"\"\"",[417,1225,754],{"class":592},[417,1227,1229,1232,1234,1236,1239,1241,1243],{"class":419,"line":1228},24,[417,1230,1231],{"class":427},"APP_PASSWORD",[417,1233,1187],{"class":585},[417,1235,1215],{"class":592},[417,1237,1238],{"class":431},"\"MICROSOFT_APP_PASSWORD\"",[417,1240,1199],{"class":592},[417,1242,1223],{"class":431},[417,1244,754],{"class":592},[417,1246,1248,1251,1253,1255,1258,1260,1262],{"class":419,"line":1247},25,[417,1249,1250],{"class":427},"APP_TYPE",[417,1252,1187],{"class":585},[417,1254,1215],{"class":592},[417,1256,1257],{"class":431},"\"MICROSOFT_APP_TYPE\"",[417,1259,1199],{"class":592},[417,1261,1223],{"class":431},[417,1263,754],{"class":592},[417,1265,1267,1270,1272,1274,1277,1279,1281],{"class":419,"line":1266},26,[417,1268,1269],{"class":427},"APP_TENANTID",[417,1271,1187],{"class":585},[417,1273,1215],{"class":592},[417,1275,1276],{"class":431},"\"MICROSOFT_APP_TENANT_ID\"",[417,1278,1199],{"class":592},[417,1280,1223],{"class":431},[417,1282,754],{"class":592},[417,1284,1286,1289,1291,1293,1295,1298,1301],{"class":419,"line":1285},27,[417,1287,1288],{"class":427},"MAX_IDLE_TIME",[417,1290,1187],{"class":585},[417,1292,1190],{"class":427},[417,1294,1193],{"class":592},[417,1296,1297],{"class":431},"\"SESSION_IDLE_LIMIT_SECS\"",[417,1299,1300],{"class":592},"))  ",[417,1302,1303],{"class":1086},"# secs\n",[417,1305,1307,1310,1312,1314,1316,1319],{"class":419,"line":1306},28,[417,1308,1309],{"class":427},"ALERT_TIME",[417,1311,1187],{"class":585},[417,1313,1190],{"class":427},[417,1315,1193],{"class":592},[417,1317,1318],{"class":431},"\"SESSION_IDLE_WARN_SECS\"",[417,1320,992],{"class":592},[417,1322,1324],{"class":419,"line":1323},29,[417,1325,654],{"emptyLinePlaceholder":193},[417,1327,1329,1332,1335,1338,1341,1344,1347,1350,1353],{"class":419,"line":1328},30,[417,1330,1331],{"class":427},"print",[417,1333,1334],{"class":592},"(",[417,1336,1337],{"class":585},"f",[417,1339,1340],{"class":431},"\"Configuration loaded. App ID: ",[417,1342,1343],{"class":427},"{APP_ID}",[417,1345,1346],{"class":431},", Port: ",[417,1348,1349],{"class":427},"{PORT}",[417,1351,1352],{"class":431},"\"",[417,1354,754],{"class":592},[417,1356,1358,1361,1363,1366,1368,1370],{"class":419,"line":1357},31,[417,1359,1360],{"class":592},"logger.info(",[417,1362,1337],{"class":585},[417,1364,1365],{"class":431},"\"✓ App ID: ",[417,1367,1343],{"class":427},[417,1369,1352],{"class":431},[417,1371,754],{"class":592},[417,1373,1375,1377,1379,1382,1385,1387],{"class":419,"line":1374},32,[417,1376,1360],{"class":592},[417,1378,1337],{"class":585},[417,1380,1381],{"class":431},"\"✓ App Type: ",[417,1383,1384],{"class":427},"{APP_TYPE}",[417,1386,1352],{"class":431},[417,1388,754],{"class":592},[417,1390,1392,1394,1396,1399,1402,1404],{"class":419,"line":1391},33,[417,1393,1360],{"class":592},[417,1395,1337],{"class":585},[417,1397,1398],{"class":431},"\"✓ Tenant ID: ",[417,1400,1401],{"class":427},"{APP_TENANTID}",[417,1403,1352],{"class":431},[417,1405,754],{"class":592},[417,1407,1409,1411,1413,1416,1419,1421,1423,1425,1428,1431,1434,1437,1439],{"class":419,"line":1408},34,[417,1410,1360],{"class":592},[417,1412,1337],{"class":585},[417,1414,1415],{"class":431},"\"✓ Password length: ",[417,1417,1418],{"class":427},"{len",[417,1420,1334],{"class":592},[417,1422,1231],{"class":427},[417,1424,704],{"class":592},[417,1426,1427],{"class":585},"if",[417,1429,1430],{"class":427}," APP_PASSWORD",[417,1432,1433],{"class":585}," else",[417,1435,1436],{"class":427}," 0}",[417,1438,1352],{"class":431},[417,1440,754],{"class":592},[417,1442,1444],{"class":419,"line":1443},35,[417,1445,654],{"emptyLinePlaceholder":193},[417,1447,1449,1451,1454,1456],{"class":419,"line":1448},36,[417,1450,1427],{"class":585},[417,1452,1453],{"class":585}," not",[417,1455,1430],{"class":427},[417,1457,614],{"class":592},[417,1459,1461,1464,1467],{"class":419,"line":1460},37,[417,1462,1463],{"class":592},"    logger.error(",[417,1465,1466],{"class":431},"\"❌ MICROSOFT_APP_PASSWORD is EMPTY!\"",[417,1468,754],{"class":592},[417,1470,1472,1474,1476,1479],{"class":419,"line":1471},38,[417,1473,1427],{"class":585},[417,1475,1453],{"class":585},[417,1477,1478],{"class":427}," APP_ID",[417,1480,614],{"class":592},[417,1482,1484,1486,1489],{"class":419,"line":1483},39,[417,1485,1463],{"class":592},[417,1487,1488],{"class":431},"\"❌ MICROSOFT_APP_ID is EMPTY!\"",[417,1490,754],{"class":592},[417,1492,1494],{"class":419,"line":1493},40,[417,1495,654],{"emptyLinePlaceholder":193},[417,1497,1499,1502,1505],{"class":419,"line":1498},41,[417,1500,1501],{"class":585},"class",[417,1503,1504],{"class":423}," BotConfig",[417,1506,614],{"class":592},[417,1508,1510,1513,1515],{"class":419,"line":1509},42,[417,1511,1512],{"class":427},"    PORT",[417,1514,1187],{"class":585},[417,1516,1517],{"class":427}," PORT\n",[417,1519,1521,1524,1526],{"class":419,"line":1520},43,[417,1522,1523],{"class":427},"    APP_TYPE",[417,1525,1187],{"class":585},[417,1527,1528],{"class":427}," APP_TYPE\n",[417,1530,1532,1535,1537],{"class":419,"line":1531},44,[417,1533,1534],{"class":427},"    APP_ID",[417,1536,1187],{"class":585},[417,1538,1539],{"class":427}," APP_ID\n",[417,1541,1543,1546,1548],{"class":419,"line":1542},45,[417,1544,1545],{"class":427},"    APP_PASSWORD",[417,1547,1187],{"class":585},[417,1549,1550],{"class":427}," APP_PASSWORD\n",[417,1552,1554,1557,1559],{"class":419,"line":1553},46,[417,1555,1556],{"class":427},"    APP_TENANTID",[417,1558,1187],{"class":585},[417,1560,1561],{"class":427}," APP_TENANTID\n",[417,1563,1565],{"class":419,"line":1564},47,[417,1566,654],{"emptyLinePlaceholder":193},[417,1568,1570,1573,1575],{"class":419,"line":1569},48,[417,1571,1572],{"class":592},"config ",[417,1574,662],{"class":585},[417,1576,1577],{"class":592}," BotConfig()\n",[417,1579,1581],{"class":419,"line":1580},49,[417,1582,1583],{"class":1086},"# Cloud Adapter is a bot\n",[417,1585,1587,1590,1592,1595,1598,1600],{"class":419,"line":1586},50,[417,1588,1589],{"class":427},"BOT_CLOUD_ADAPTER",[417,1591,1187],{"class":585},[417,1593,1594],{"class":592}," CloudAdapter(ConfigurationBotFrameworkAuthentication(config, ",[417,1596,1597],{"class":1099},"logger",[417,1599,662],{"class":585},[417,1601,1602],{"class":592},"logger))\n",[417,1604,1606],{"class":419,"line":1605},51,[417,1607,654],{"emptyLinePlaceholder":193},[417,1609,1611],{"class":419,"line":1610},52,[417,1612,654],{"emptyLinePlaceholder":193},[417,1614,1616,1619,1621,1623,1626,1628,1631,1634,1637,1640,1643,1645,1647,1649,1652,1654,1657],{"class":419,"line":1615},53,[417,1617,1618],{"class":592},"return_last_message_only ",[417,1620,662],{"class":585},[417,1622,1215],{"class":592},[417,1624,1625],{"class":431},"\"BOT_BACKEND_LAST_MSG_ONLY\"",[417,1627,1199],{"class":592},[417,1629,1630],{"class":431},"\"true\"",[417,1632,1633],{"class":592},").strip().lower() ",[417,1635,1636],{"class":585},"in",[417,1638,1639],{"class":592}," (",[417,1641,1642],{"class":431},"\"1\"",[417,1644,1199],{"class":592},[417,1646,1630],{"class":431},[417,1648,1199],{"class":592},[417,1650,1651],{"class":431},"\"yes\"",[417,1653,1199],{"class":592},[417,1655,1656],{"class":431},"\"on\"",[417,1658,754],{"class":592},[417,1660,1662,1665,1667,1669,1672],{"class":419,"line":1661},54,[417,1663,1664],{"class":592},"query_url ",[417,1666,662],{"class":585},[417,1668,1215],{"class":592},[417,1670,1671],{"class":431},"\"BOT_BACKEND_ENDPOINT\"",[417,1673,754],{"class":592},[417,1675,1677,1679,1681],{"class":419,"line":1676},55,[417,1678,1427],{"class":585},[417,1680,1453],{"class":585},[417,1682,1683],{"class":592}," query_url:\n",[417,1685,1687,1690,1693,1695,1698],{"class":419,"line":1686},56,[417,1688,1689],{"class":585},"    raise",[417,1691,1692],{"class":427}," ValueError",[417,1694,1334],{"class":592},[417,1696,1697],{"class":431},"\"BOT_BACKEND_ENDPOINT is required\"",[417,1699,754],{"class":592},[417,1701,1703],{"class":419,"line":1702},57,[417,1704,654],{"emptyLinePlaceholder":193},[417,1706,1708,1711,1713],{"class":419,"line":1707},58,[417,1709,1710],{"class":592},"chatbot_adapter ",[417,1712,662],{"class":585},[417,1714,1715],{"class":592}," AgentEngineADKAdapter(\n",[417,1717,1719,1722,1724],{"class":419,"line":1718},59,[417,1720,1721],{"class":1099},"    query_url",[417,1723,662],{"class":585},[417,1725,1726],{"class":592},"query_url,\n",[417,1728,1730,1733,1735,1737,1739,1742,1744,1747],{"class":419,"line":1729},60,[417,1731,1732],{"class":1099},"    timeout_seconds",[417,1734,662],{"class":585},[417,1736,596],{"class":427},[417,1738,1193],{"class":592},[417,1740,1741],{"class":431},"\"BOT_BACKEND_TIMEOUT_SECS\"",[417,1743,1199],{"class":592},[417,1745,1746],{"class":431},"\"60\"",[417,1748,1749],{"class":592},")),\n",[417,1751,1753,1756,1758],{"class":419,"line":1752},61,[417,1754,1755],{"class":1099},"    return_last_message_only",[417,1757,662],{"class":585},[417,1759,1760],{"class":592},"return_last_message_only,\n",[417,1762,1764,1767,1769,1772,1775,1777,1780],{"class":419,"line":1763},62,[417,1765,1766],{"class":1099},"    class_method",[417,1768,662],{"class":585},[417,1770,1771],{"class":592},"os.environ.get(",[417,1773,1774],{"class":431},"\"BOT_BACKEND_CLASS_METHOD\"",[417,1776,1199],{"class":592},[417,1778,1779],{"class":431},"\"async_stream_query\"",[417,1781,1782],{"class":592},"),\n",[417,1784,1786],{"class":419,"line":1785},63,[417,1787,754],{"class":592},[417,1789,1791,1793,1796],{"class":419,"line":1790},64,[417,1792,1360],{"class":592},[417,1794,1795],{"class":431},"\"Agent Engine REST adapter initialized as primary chatbot adapter\"",[417,1797,754],{"class":592},[417,1799,1801],{"class":419,"line":1800},65,[417,1802,654],{"emptyLinePlaceholder":193},[417,1804,1806],{"class":419,"line":1805},66,[417,1807,1808],{"class":1086},"# Plug in whatever session store you use (a database, cache, etc.)\n",[417,1810,1812,1815,1817],{"class":419,"line":1811},67,[417,1813,1814],{"class":592},"data_store ",[417,1816,662],{"class":585},[417,1818,1819],{"class":592}," SessionStoreAdapter(\n",[417,1821,1823,1826,1828,1830,1833],{"class":419,"line":1822},68,[417,1824,1825],{"class":1099},"    connection_string",[417,1827,662],{"class":585},[417,1829,1771],{"class":592},[417,1831,1832],{"class":431},"\"DATASTORE_DSN\"",[417,1834,1782],{"class":592},[417,1836,1838],{"class":419,"line":1837},69,[417,1839,754],{"class":592},[417,1841,1843,1845,1848],{"class":419,"line":1842},70,[417,1844,1360],{"class":592},[417,1846,1847],{"class":431},"\"Session store adapter initialized\"",[417,1849,754],{"class":592},[417,1851,1853],{"class":419,"line":1852},71,[417,1854,654],{"emptyLinePlaceholder":193},[417,1856,1858],{"class":419,"line":1857},72,[417,1859,1860],{"class":1086},"# Plug in whatever feedback storage you use\n",[417,1862,1864,1867,1869],{"class":419,"line":1863},73,[417,1865,1866],{"class":592},"feedback_repository ",[417,1868,662],{"class":585},[417,1870,1871],{"class":592}," FeedbackRepository(\n",[417,1873,1875,1877,1879,1881,1884],{"class":419,"line":1874},74,[417,1876,1825],{"class":1099},[417,1878,662],{"class":585},[417,1880,1771],{"class":592},[417,1882,1883],{"class":431},"\"FEEDBACK_DSN\"",[417,1885,1782],{"class":592},[417,1887,1889],{"class":419,"line":1888},75,[417,1890,754],{"class":592},[417,1892,1894],{"class":419,"line":1893},76,[417,1895,654],{"emptyLinePlaceholder":193},[417,1897,1899,1902,1904],{"class":419,"line":1898},77,[417,1900,1901],{"class":592},"feedback_handler ",[417,1903,662],{"class":585},[417,1905,1906],{"class":592}," DefaultFeedbackHandler(feedback_repository)\n",[417,1908,1910],{"class":419,"line":1909},78,[417,1911,654],{"emptyLinePlaceholder":193},[417,1913,1915,1918,1920],{"class":419,"line":1914},79,[417,1916,1917],{"class":592},"bot_service ",[417,1919,662],{"class":585},[417,1921,1922],{"class":592}," BotService(\n",[417,1924,1926,1929,1931],{"class":419,"line":1925},80,[417,1927,1928],{"class":1099},"    chatbot_adapter",[417,1930,662],{"class":585},[417,1932,1933],{"class":592},"chatbot_adapter,\n",[417,1935,1937,1940,1942],{"class":419,"line":1936},81,[417,1938,1939],{"class":1099},"    data_store",[417,1941,662],{"class":585},[417,1943,1944],{"class":592},"data_store,\n",[417,1946,1948,1951,1953,1956],{"class":419,"line":1947},82,[417,1949,1950],{"class":1099},"    fallback_adapter",[417,1952,662],{"class":585},[417,1954,1955],{"class":427},"None",[417,1957,1958],{"class":592},",\n",[417,1960,1962,1965,1967,1969],{"class":419,"line":1961},83,[417,1963,1964],{"class":1099},"    bot_adapter",[417,1966,662],{"class":585},[417,1968,1589],{"class":427},[417,1970,1958],{"class":592},[417,1972,1974,1977,1979,1981],{"class":419,"line":1973},84,[417,1975,1976],{"class":1099},"    app_id",[417,1978,662],{"class":585},[417,1980,1210],{"class":427},[417,1982,1958],{"class":592},[417,1984,1986,1989,1991],{"class":419,"line":1985},85,[417,1987,1988],{"class":1099},"    feedback_handler",[417,1990,662],{"class":585},[417,1992,1993],{"class":592},"feedback_handler,\n",[417,1995,1997,2000,2002,2004],{"class":419,"line":1996},86,[417,1998,1999],{"class":1099},"    alert_idle_seconds",[417,2001,662],{"class":585},[417,2003,1309],{"class":427},[417,2005,1958],{"class":592},[417,2007,2009,2012,2014,2016],{"class":419,"line":2008},87,[417,2010,2011],{"class":1099},"    close_idle_seconds",[417,2013,662],{"class":585},[417,2015,1288],{"class":427},[417,2017,1958],{"class":592},[417,2019,2021],{"class":419,"line":2020},88,[417,2022,754],{"class":592},[417,2024,2026],{"class":419,"line":2025},89,[417,2027,654],{"emptyLinePlaceholder":193},[417,2029,2031,2034,2036,2039,2041,2043,2045],{"class":419,"line":2030},90,[417,2032,2033],{"class":592},"incoming_events_handler ",[417,2035,662],{"class":585},[417,2037,2038],{"class":592}," BotInconmingEventsHandler(",[417,2040,1210],{"class":427},[417,2042,1199],{"class":592},[417,2044,1231],{"class":427},[417,2046,2047],{"class":592},", bot_service)\n",[417,2049,2051],{"class":419,"line":2050},91,[417,2052,654],{"emptyLinePlaceholder":193},[417,2054,2056,2059,2061,2064,2066],{"class":419,"line":2055},92,[417,2057,2058],{"class":592},"http_adapter ",[417,2060,662],{"class":585},[417,2062,2063],{"class":592}," HTTPAdapter(",[417,2065,1589],{"class":427},[417,2067,2068],{"class":592},", incoming_events_handler)\n",[417,2070,2072,2075,2077],{"class":419,"line":2071},93,[417,2073,2074],{"class":592},"app ",[417,2076,662],{"class":585},[417,2078,2079],{"class":592}," http_adapter.get_app()\n",[417,2081,2083],{"class":419,"line":2082},94,[417,2084,654],{"emptyLinePlaceholder":193},[417,2086,2088],{"class":419,"line":2087},95,[417,2089,2090],{"class":1086},"# Start session watcher if data store is available\n",[417,2092,2094,2096,2099,2102,2104,2107],{"class":419,"line":2093},96,[417,2095,1427],{"class":585},[417,2097,2098],{"class":592}," data_store ",[417,2100,2101],{"class":585},"is",[417,2103,1453],{"class":585},[417,2105,2106],{"class":427}," None",[417,2108,614],{"class":592},[417,2110,2112,2115],{"class":419,"line":2111},97,[417,2113,2114],{"class":585},"    try",[417,2116,614],{"class":592},[417,2118,2120,2123,2125,2128,2131,2133,2135],{"class":419,"line":2119},98,[417,2121,2122],{"class":592},"        watcher ",[417,2124,662],{"class":585},[417,2126,2127],{"class":592}," SessionWatcher(data_store, bot_service, ",[417,2129,2130],{"class":1099},"alert_idle_seconds",[417,2132,662],{"class":585},[417,2134,1309],{"class":427},[417,2136,1958],{"class":592},[417,2138,2140,2143,2145,2147],{"class":419,"line":2139},99,[417,2141,2142],{"class":1099},"                                 close_idle_seconds",[417,2144,662],{"class":585},[417,2146,1288],{"class":427},[417,2148,754],{"class":592},[417,2150,2152],{"class":419,"line":2151},100,[417,2153,2154],{"class":592},"        watcher.start()\n",[417,2156,2158,2161,2164,2167],{"class":419,"line":2157},101,[417,2159,2160],{"class":585},"    except",[417,2162,2163],{"class":427}," Exception",[417,2165,2166],{"class":585}," as",[417,2168,2169],{"class":592}," e:\n",[417,2171,2173,2176,2178,2180,2183,2186,2189,2192,2194],{"class":419,"line":2172},102,[417,2174,2175],{"class":427},"        print",[417,2177,1334],{"class":592},[417,2179,1337],{"class":585},[417,2181,2182],{"class":431},"\"Warning: could not start session watcher: ",[417,2184,2185],{"class":427},"{",[417,2187,2188],{"class":592},"e",[417,2190,2191],{"class":427},"}",[417,2193,1352],{"class":431},[417,2195,754],{"class":592},[417,2197,2199],{"class":419,"line":2198},103,[417,2200,654],{"emptyLinePlaceholder":193},[417,2202,2204,2206,2209,2212,2215],{"class":419,"line":2203},104,[417,2205,1427],{"class":585},[417,2207,2208],{"class":427}," __name__",[417,2210,2211],{"class":585}," ==",[417,2213,2214],{"class":431}," \"__main__\"",[417,2216,614],{"class":592},[417,2218,2220,2223,2226,2228],{"class":419,"line":2219},105,[417,2221,2222],{"class":585},"    from",[417,2224,2225],{"class":592}," aiohttp ",[417,2227,965],{"class":585},[417,2229,2230],{"class":592}," web\n",[417,2232,2234,2236],{"class":419,"line":2233},106,[417,2235,2114],{"class":585},[417,2237,614],{"class":592},[417,2239,2241,2244,2247,2249,2252,2254,2257,2259,2261],{"class":419,"line":2240},107,[417,2242,2243],{"class":592},"        web.run_app(app, ",[417,2245,2246],{"class":1099},"host",[417,2248,662],{"class":585},[417,2250,2251],{"class":431},"\"0.0.0.0\"",[417,2253,1199],{"class":592},[417,2255,2256],{"class":1099},"port",[417,2258,662],{"class":585},[417,2260,1184],{"class":427},[417,2262,754],{"class":592},[417,2264,2266,2268,2270,2272],{"class":419,"line":2265},108,[417,2267,2160],{"class":585},[417,2269,2163],{"class":427},[417,2271,2166],{"class":585},[417,2273,2274],{"class":592}," error:\n",[417,2276,2278,2281],{"class":419,"line":2277},109,[417,2279,2280],{"class":585},"        raise",[417,2282,2283],{"class":592}," error\n",[219,2285,2286,2287,2291],{},"Puedes revisar más implementaciones en el Quickstart de Microsoft ",[251,2288,2290],{"href":2289},"#ref-2","[2]",".\nEn mi opinión la página está abandonada, así que no asumas que funcionará tal cual.",[951,2293,2294],{"start":188},[242,2295,2296],{},"Antes de dar por terminada tu integración no olvides recopilar estas variables correctamente. Son necesarias para desencriptar la comunicación de Azure en el entorno productivo.",[408,2298,2300],{"className":410,"code":2299,"language":412,"meta":187,"style":187},"MicrosoftAppType= SingleTenant\nMicrosoftAppId= # client id you just used for entra id and bot services\nMicrosoftAppPassword= # client secret\nMicrosoftAppTenantId=\n",[414,2301,2302,2312,2322,2332],{"__ignoreMap":187},[417,2303,2304,2307,2309],{"class":419,"line":420},[417,2305,2306],{"class":592},"MicrosoftAppType",[417,2308,662],{"class":585},[417,2310,2311],{"class":423}," SingleTenant\n",[417,2313,2314,2317,2319],{"class":419,"line":188},[417,2315,2316],{"class":592},"MicrosoftAppId",[417,2318,662],{"class":585},[417,2320,2321],{"class":1086}," # client id you just used for entra id and bot services\n",[417,2323,2324,2327,2329],{"class":419,"line":445},[417,2325,2326],{"class":592},"MicrosoftAppPassword",[417,2328,662],{"class":585},[417,2330,2331],{"class":1086}," # client secret\n",[417,2333,2334,2337],{"class":419,"line":456},[417,2335,2336],{"class":592},"MicrosoftAppTenantId",[417,2338,2339],{"class":585},"=\n",[219,2341,2342],{},"El client secret solo es necesario para integraciones fuera del ecosistema de Azure. Es preferible usar OAuth2 o un método libre de secretos.",[263,2344,2346],{"id":2345},"y-también-tienes-un-bonito-playground-para-que-pruebes-tu-agente-incluso-antes-de-tenerlo-en-microsoft-365","Y también tienes un bonito playground para que pruebes tu agente incluso antes de tenerlo en Microsoft 365",[219,2348,2349],{},"Para que no falle debes dejar vacías las variables que vimos en el paso #2.\nSi no lo haces el playground no podrá desencriptar las comunicaciones. Y en mi experiencia ha sido complicado debuggear cuando falla.",[219,2351,2352,2356],{},[222,2353],{"alt":2354,"src":2355,"title":2354},"Playground de Microsoft 365","\u002Farticles\u002F2026\u002Fjuly\u002Fmicrosoft-365-playground.png",[335,2357,2354],{},[258,2359,2361],{"id":2360},"publicación-en-teams","Publicación en Teams",[263,2363,2365],{"id":2364},"carga-el-archivo-exportado-de-365-toolkit","Carga el Archivo Exportado de 365 Toolkit",[219,2367,2368],{},"El proyecto que has configurado previamente genera un bundle. Lo puedes personalizar con el logo que quieres que se muestre.\nUna versión a color y otra simplificada para las sidebars e íconos pequeños.",[219,2370,2371,2375],{},[222,2372],{"alt":2373,"src":2374,"title":2373},"Solicitud de carga de la app a Teams","\u002Farticles\u002F2026\u002Fjuly\u002Fupload-app-to-teams-request.png",[335,2376,2377],{},"Carga del bundle exportado desde el Toolkit",[263,2379,2381],{"id":2380},"contacta-con-tu-administrador-de-ms-365","Contacta con Tu Administrador de MS 365",[219,2383,2384],{},"Dirígelo a estos enlaces:",[239,2386,2387,2394],{},[242,2388,2389,2390],{},"Centro de administración de Microsoft Teams ",[251,2391,2393],{"href":2392},"#ref-4","[4]",[242,2395,2396,2397],{},"Centro de administración de Microsoft 365 ",[251,2398,2400],{"href":2399},"#ref-5","[5]",[219,2402,2403],{},"No he podido cargarte pantallas de cómo se ve la consola de administrador y exactamente qué pasos debe tomar tu administrador.\nPero hazle saber que puede crear listas de acceso para la aplicación.",[219,2405,2406],{},"En específico debería tener una lista de acceso para la aplicación dev, que solo está abierta para unos pocos usuarios testers y desarrolladores.\nY para la aplicación productiva se puede ir planteando una estrategia distinta.",[258,2408,2410],{"id":2409},"cx","CX!",[263,2412,2414],{"id":2413},"te-interesa-usar-formularios-con-tu-agente","¿Te interesa usar formularios con tu agente?",[219,2416,2417,2418,2422],{},"Las tarjetas adaptativas de toda la vida de Microsoft ",[251,2419,2421],{"href":2420},"#ref-3","[3]",". Las puedes usar en tu middleware.\n¿Personalización extra? Es el mismo estándar que Power Automate, con el que podrías estar más familiarizado.",[263,2424,2426],{"id":2425},"quieres-que-el-bot-escriba","¿Quieres que ... el ... bot ... escriba? ...",[408,2428,2430],{"className":576,"code":2429,"language":578,"meta":187,"style":187},"# Typying activity: ...\nawait turn_context.send_activity(Activity(type=ActivityTypes.typing))\n# Delegate to application service\nresponse = await self.bot_service.handle_message(text, turn_context)\nawait turn_context.send_activity(response)\n",[414,2431,2432,2437,2453,2458,2474],{"__ignoreMap":187},[417,2433,2434],{"class":419,"line":420},[417,2435,2436],{"class":1086},"# Typying activity: ...\n",[417,2438,2439,2442,2445,2448,2450],{"class":419,"line":188},[417,2440,2441],{"class":585},"await",[417,2443,2444],{"class":592}," turn_context.send_activity(Activity(",[417,2446,2447],{"class":1099},"type",[417,2449,662],{"class":585},[417,2451,2452],{"class":592},"ActivityTypes.typing))\n",[417,2454,2455],{"class":419,"line":445},[417,2456,2457],{"class":1086},"# Delegate to application service\n",[417,2459,2460,2463,2465,2468,2471],{"class":419,"line":456},[417,2461,2462],{"class":592},"response ",[417,2464,662],{"class":585},[417,2466,2467],{"class":585}," await",[417,2469,2470],{"class":427}," self",[417,2472,2473],{"class":592},".bot_service.handle_message(text, turn_context)\n",[417,2475,2476,2478],{"class":419,"line":466},[417,2477,2441],{"class":585},[417,2479,2480],{"class":592}," turn_context.send_activity(response)\n",[219,2482,2483],{},"Con enviar esa actividad es suficiente en lo que tu motor del agente responde.",[258,2485,2487],{"id":2486},"extra","Extra!",[219,2489,2490],{},"Esto es lo que pude recopilar de las comunicación que envían los servidores de Azure Bot Services. Te podría ser útil si quieres entender qué tanto puedes obtener de información útil a través del middleware.",[408,2492,2496],{"className":2493,"code":2494,"language":2495,"meta":187,"style":187},"language-http shiki shiki-themes github-light github-dark","POST \u002Fapi\u002Fmessages HTTP\u002F1.1\nHost: localhost:3978\nUser-Agent: BF-DirectLine (Microsoft-BotFramework\u002F3.2 +https:\u002F\u002Fbotframework.com\u002Fua)\nContent-Length: 719\nAccept: *\u002F*\nAuthorization: Bearer \u003CREDACTED_JWT>\nChannelid: webchat\nContent-Type: application\u002Fjson; charset=utf-8\nRequest-Id: |\u003CREDACTED_REQUEST_ID>.\u003CREDACTED_SPAN_ID>.\nTraceparent: 00-\u003CREDACTED_TRACE_ID>-\u003CREDACTED_SPAN_ID>-00\nX-Forwarded-For: xxx.xxx.xxx.xxx\nX-Forwarded-Host: xxxx-xxx-xxx-xx.ngrok-free.app\nX-Forwarded-Proto: https\nX-Ms-Conversation-Id: \u003CREDACTED_CONVERSATION_ID>\nAccept-Encoding: gzip\n\n{\"type\":\"typing\",\"id\":\"\u003CREDACTED_CONVERSATION_ID>|\u003CREDACTED_ACTIVITY_ID>\",\"timestamp\":\"2026-03-02T17:44:41.6782359Z\",\"localTimestamp\":\"2026-03-02T12:44:41.391-05:00\",\"localTimezone\":\"America\u002FLima\",\"serviceUrl\":\"https:\u002F\u002Fwebchat.botframework.com\u002F\",\"channelId\":\"webchat\",\"from\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"name\":\"\"},\"conversation\":{\"id\":\"\u003CREDACTED_CONVERSATION_ID>\"},\"recipient\":{\"id\":\"agente-msteams@\u003CREDACTED_TOKEN>\",\"name\":\"agente-msteams\"},\"locale\":\"en-US\",\"entities\":[{\"type\":\"ClientCapabilities\",\"requiresBotState\":true,\"supportsListening\":true,\"supportsTts\":true}],\"channelData\":{\"clientActivityID\":\"\u003CREDACTED_CLIENT_ACTIVITY_ID>\"}}\n\n\n\n\nPOST \u002Fapi\u002Fmessages HTTP\u002F1.1\nHost: localhost:3978\nUser-Agent: BF-DirectLine (Microsoft-BotFramework\u002F3.2 +https:\u002F\u002Fbotframework.com\u002Fua)\nContent-Length: 662\nAccept: *\u002F*\nAuthorization: Bearer \u003CREDACTED_JWT>\nChannelid: webchat\nContent-Type: application\u002Fjson; charset=utf-8\nRequest-Id: |\u003CREDACTED_REQUEST_ID>.\u003CREDACTED_SPAN_ID>.\nTraceparent: 00-\u003CREDACTED_TRACE_ID>-\u003CREDACTED_SPAN_ID>-00\nX-Forwarded-For: xxx.xxx.xxx.xxx\nX-Forwarded-Host: xxxx-xxx-xxx-xx.ngrok-free.app\nX-Forwarded-Proto: https\nX-Ms-Conversation-Id: \u003CREDACTED_CONVERSATION_ID>\nAccept-Encoding: gzip\n\n{\"type\":\"conversationUpdate\",\"id\":\"\u003CREDACTED_ACTIVITY_ID>\",\"timestamp\":\"2026-03-02T17:44:41.0353977Z\",\"serviceUrl\":\"https:\u002F\u002Fwebchat.botframework.com\u002F\",\"channelId\":\"webchat\",\"from\":{\"id\":\"00000000-0000-0000-0000-000000000000\"},\"conversation\":{\"id\":\"\u003CREDACTED_CONVERSATION_ID>\"},\"recipient\":{\"id\":\"agente-msteams@\u003CREDACTED_TOKEN>\",\"name\":\"agente-msteams\"},\"membersAdded\":[{\"id\":\"agente-msteams@\u003CREDACTED_TOKEN>\",\"name\":\"agente-msteams\"},{\"id\":\"00000000-0000-0000-0000-000000000000\"}]}\n\nPOST \u002Fapi\u002Fmessages HTTP\u002F1.1\nHost: localhost:3978\nUser-Agent: BF-DirectLine (Microsoft-BotFramework\u002F3.2 +https:\u002F\u002Fbotframework.com\u002Fua)\nContent-Length: 679\nAccept: *\u002F*\nAuthorization: Bearer \u003CREDACTED_JWT>\nChannelid: webchat\nContent-Type: application\u002Fjson; charset=utf-8\nRequest-Id: |\u003CREDACTED_REQUEST_ID>.\u003CREDACTED_SPAN_ID>.\nTraceparent: 00-\u003CREDACTED_TRACE_ID>-\u003CREDACTED_SPAN_ID>-00\nX-Forwarded-For: xxx.xxx.xxx.xxx\nX-Forwarded-Host: xxxx-xxx-xxx-xx.ngrok-free.app\nX-Forwarded-Proto: https\nX-Ms-Conversation-Id: \u003CREDACTED_CONVERSATION_ID>\nAccept-Encoding: gzip\n\n{\"type\":\"message\",\"id\":\"\u003CREDACTED_CONVERSATION_ID>|\u003CREDACTED_ACTIVITY_ID>\",\"timestamp\":\"2026-03-02T17:44:42.8691754Z\",\"localTimestamp\":\"2026-03-02T12:44:42.728-05:00\",\"localTimezone\":\"America\u002FLima\",\"serviceUrl\":\"https:\u002F\u002Fwebchat.botframework.com\u002F\",\"channelId\":\"webchat\",\"from\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"name\":\"\"},\"conversation\":{\"id\":\"\u003CREDACTED_CONVERSATION_ID>\"},\"recipient\":{\"id\":\"agente-msteams@\u003CREDACTED_TOKEN>\",\"name\":\"agente-msteams\"},\"textFormat\":\"plain\",\"locale\":\"en-US\",\"text\":\"Hola\",\"attachments\":[],\"channelData\":{\"attachmentSizes\":[],\"clientActivityID\":\"\u003CREDACTED_CLIENT_ACTIVITY_ID>\"}}\n","http",[414,2497,2498,2514,2526,2536,2546,2556,2566,2576,2586,2596,2606,2616,2626,2636,2646,2656,2660,2867,2871,2875,2879,2883,2890,2898,2912,2920,2928,2933,2938,2943,2948,2953,2958,2963,2968,2973,2978,2982,2987,2991,2996,3001,3006,3011,3019,3023,3027,3035,3039,3053,3057,3061,3065,3069,3073,3077],{"__ignoreMap":187},[417,2499,2500,2503,2506,2509,2511],{"class":419,"line":420},[417,2501,2502],{"class":585},"POST",[417,2504,2505],{"class":592}," \u002Fapi\u002Fmessages ",[417,2507,2508],{"class":585},"HTTP",[417,2510,707],{"class":592},[417,2512,2513],{"class":427},"1.1\n",[417,2515,2516,2520,2523],{"class":419,"line":188},[417,2517,2519],{"class":2518},"s9eBZ","Host",[417,2521,2522],{"class":585},":",[417,2524,2525],{"class":431}," localhost:3978\n",[417,2527,2528,2531,2533],{"class":419,"line":445},[417,2529,2530],{"class":2518},"User-Agent",[417,2532,2522],{"class":585},[417,2534,2535],{"class":431}," BF-DirectLine (Microsoft-BotFramework\u002F3.2 +https:\u002F\u002Fbotframework.com\u002Fua)\n",[417,2537,2538,2541,2543],{"class":419,"line":456},[417,2539,2540],{"class":2518},"Content-Length",[417,2542,2522],{"class":585},[417,2544,2545],{"class":431}," 719\n",[417,2547,2548,2551,2553],{"class":419,"line":466},[417,2549,2550],{"class":2518},"Accept",[417,2552,2522],{"class":585},[417,2554,2555],{"class":431}," *\u002F*\n",[417,2557,2558,2561,2563],{"class":419,"line":518},[417,2559,2560],{"class":2518},"Authorization",[417,2562,2522],{"class":585},[417,2564,2565],{"class":431}," Bearer \u003CREDACTED_JWT>\n",[417,2567,2568,2571,2573],{"class":419,"line":524},[417,2569,2570],{"class":2518},"Channelid",[417,2572,2522],{"class":585},[417,2574,2575],{"class":431}," webchat\n",[417,2577,2578,2581,2583],{"class":419,"line":530},[417,2579,2580],{"class":2518},"Content-Type",[417,2582,2522],{"class":585},[417,2584,2585],{"class":431}," application\u002Fjson; charset=utf-8\n",[417,2587,2588,2591,2593],{"class":419,"line":1039},[417,2589,2590],{"class":2518},"Request-Id",[417,2592,2522],{"class":585},[417,2594,2595],{"class":431}," |\u003CREDACTED_REQUEST_ID>.\u003CREDACTED_SPAN_ID>.\n",[417,2597,2598,2601,2603],{"class":419,"line":1052},[417,2599,2600],{"class":2518},"Traceparent",[417,2602,2522],{"class":585},[417,2604,2605],{"class":431}," 00-\u003CREDACTED_TRACE_ID>-\u003CREDACTED_SPAN_ID>-00\n",[417,2607,2608,2611,2613],{"class":419,"line":1065},[417,2609,2610],{"class":2518},"X-Forwarded-For",[417,2612,2522],{"class":585},[417,2614,2615],{"class":431}," xxx.xxx.xxx.xxx\n",[417,2617,2618,2621,2623],{"class":419,"line":1070},[417,2619,2620],{"class":2518},"X-Forwarded-Host",[417,2622,2522],{"class":585},[417,2624,2625],{"class":431}," xxxx-xxx-xxx-xx.ngrok-free.app\n",[417,2627,2628,2631,2633],{"class":419,"line":1078},[417,2629,2630],{"class":2518},"X-Forwarded-Proto",[417,2632,2522],{"class":585},[417,2634,2635],{"class":431}," https\n",[417,2637,2638,2641,2643],{"class":419,"line":1083},[417,2639,2640],{"class":2518},"X-Ms-Conversation-Id",[417,2642,2522],{"class":585},[417,2644,2645],{"class":431}," \u003CREDACTED_CONVERSATION_ID>\n",[417,2647,2648,2651,2653],{"class":419,"line":1090},[417,2649,2650],{"class":2518},"Accept-Encoding",[417,2652,2522],{"class":585},[417,2654,2655],{"class":431}," gzip\n",[417,2657,2658],{"class":419,"line":1096},[417,2659,654],{"emptyLinePlaceholder":193},[417,2661,2662,2664,2667,2669,2672,2675,2678,2680,2683,2685,2688,2690,2693,2695,2698,2700,2703,2705,2708,2710,2713,2715,2718,2720,2723,2725,2728,2730,2733,2735,2738,2741,2743,2745,2748,2750,2753,2755,2757,2760,2763,2765,2767,2769,2772,2774,2777,2779,2781,2783,2786,2788,2790,2792,2795,2797,2800,2802,2805,2807,2810,2813,2815,2817,2820,2822,2825,2827,2830,2832,2835,2837,2839,2841,2844,2846,2848,2851,2854,2856,2859,2861,2864],{"class":419,"line":1117},[417,2663,2185],{"class":592},[417,2665,2666],{"class":427},"\"type\"",[417,2668,2522],{"class":592},[417,2670,2671],{"class":431},"\"typing\"",[417,2673,2674],{"class":592},",",[417,2676,2677],{"class":427},"\"id\"",[417,2679,2522],{"class":592},[417,2681,2682],{"class":431},"\"\u003CREDACTED_CONVERSATION_ID>|\u003CREDACTED_ACTIVITY_ID>\"",[417,2684,2674],{"class":592},[417,2686,2687],{"class":427},"\"timestamp\"",[417,2689,2522],{"class":592},[417,2691,2692],{"class":431},"\"2026-03-02T17:44:41.6782359Z\"",[417,2694,2674],{"class":592},[417,2696,2697],{"class":427},"\"localTimestamp\"",[417,2699,2522],{"class":592},[417,2701,2702],{"class":431},"\"2026-03-02T12:44:41.391-05:00\"",[417,2704,2674],{"class":592},[417,2706,2707],{"class":427},"\"localTimezone\"",[417,2709,2522],{"class":592},[417,2711,2712],{"class":431},"\"America\u002FLima\"",[417,2714,2674],{"class":592},[417,2716,2717],{"class":427},"\"serviceUrl\"",[417,2719,2522],{"class":592},[417,2721,2722],{"class":431},"\"https:\u002F\u002Fwebchat.botframework.com\u002F\"",[417,2724,2674],{"class":592},[417,2726,2727],{"class":427},"\"channelId\"",[417,2729,2522],{"class":592},[417,2731,2732],{"class":431},"\"webchat\"",[417,2734,2674],{"class":592},[417,2736,2737],{"class":427},"\"from\"",[417,2739,2740],{"class":592},":{",[417,2742,2677],{"class":427},[417,2744,2522],{"class":592},[417,2746,2747],{"class":431},"\"00000000-0000-0000-0000-000000000000\"",[417,2749,2674],{"class":592},[417,2751,2752],{"class":427},"\"name\"",[417,2754,2522],{"class":592},[417,2756,1223],{"class":431},[417,2758,2759],{"class":592},"},",[417,2761,2762],{"class":427},"\"conversation\"",[417,2764,2740],{"class":592},[417,2766,2677],{"class":427},[417,2768,2522],{"class":592},[417,2770,2771],{"class":431},"\"\u003CREDACTED_CONVERSATION_ID>\"",[417,2773,2759],{"class":592},[417,2775,2776],{"class":427},"\"recipient\"",[417,2778,2740],{"class":592},[417,2780,2677],{"class":427},[417,2782,2522],{"class":592},[417,2784,2785],{"class":431},"\"agente-msteams@\u003CREDACTED_TOKEN>\"",[417,2787,2674],{"class":592},[417,2789,2752],{"class":427},[417,2791,2522],{"class":592},[417,2793,2794],{"class":431},"\"agente-msteams\"",[417,2796,2759],{"class":592},[417,2798,2799],{"class":427},"\"locale\"",[417,2801,2522],{"class":592},[417,2803,2804],{"class":431},"\"en-US\"",[417,2806,2674],{"class":592},[417,2808,2809],{"class":427},"\"entities\"",[417,2811,2812],{"class":592},":[{",[417,2814,2666],{"class":427},[417,2816,2522],{"class":592},[417,2818,2819],{"class":431},"\"ClientCapabilities\"",[417,2821,2674],{"class":592},[417,2823,2824],{"class":427},"\"requiresBotState\"",[417,2826,2522],{"class":592},[417,2828,2829],{"class":427},"true",[417,2831,2674],{"class":592},[417,2833,2834],{"class":427},"\"supportsListening\"",[417,2836,2522],{"class":592},[417,2838,2829],{"class":427},[417,2840,2674],{"class":592},[417,2842,2843],{"class":427},"\"supportsTts\"",[417,2845,2522],{"class":592},[417,2847,2829],{"class":427},[417,2849,2850],{"class":592},"}],",[417,2852,2853],{"class":427},"\"channelData\"",[417,2855,2740],{"class":592},[417,2857,2858],{"class":427},"\"clientActivityID\"",[417,2860,2522],{"class":592},[417,2862,2863],{"class":431},"\"\u003CREDACTED_CLIENT_ACTIVITY_ID>\"",[417,2865,2866],{"class":592},"}}\n",[417,2868,2869],{"class":419,"line":1150},[417,2870,654],{"emptyLinePlaceholder":193},[417,2872,2873],{"class":419,"line":1155},[417,2874,654],{"emptyLinePlaceholder":193},[417,2876,2877],{"class":419,"line":1160},[417,2878,654],{"emptyLinePlaceholder":193},[417,2880,2881],{"class":419,"line":1176},[417,2882,654],{"emptyLinePlaceholder":193},[417,2884,2885,2888],{"class":419,"line":1181},[417,2886,2887],{"class":592},"POST \u002Fapi\u002Fmessages HTTP\u002F",[417,2889,2513],{"class":427},[417,2891,2892,2895],{"class":419,"line":1207},[417,2893,2894],{"class":592},"Host: localhost:",[417,2896,2897],{"class":427},"3978\n",[417,2899,2900,2903,2906,2909],{"class":419,"line":1228},[417,2901,2902],{"class":592},"User-Agent: BF-DirectLine (Microsoft-BotFramework\u002F",[417,2904,2905],{"class":427},"3.2",[417,2907,2908],{"class":592}," +https:",[417,2910,2911],{"class":1086},"\u002F\u002Fbotframework.com\u002Fua)\n",[417,2913,2914,2917],{"class":419,"line":1247},[417,2915,2916],{"class":592},"Content-Length: ",[417,2918,2919],{"class":427},"662\n",[417,2921,2922,2925],{"class":419,"line":1266},[417,2923,2924],{"class":592},"Accept: *",[417,2926,2927],{"class":1086},"\u002F*\n",[417,2929,2930],{"class":419,"line":1285},[417,2931,2932],{"class":1086},"Authorization: Bearer \u003CREDACTED_JWT>\n",[417,2934,2935],{"class":419,"line":1306},[417,2936,2937],{"class":1086},"Channelid: webchat\n",[417,2939,2940],{"class":419,"line":1323},[417,2941,2942],{"class":1086},"Content-Type: application\u002Fjson; charset=utf-8\n",[417,2944,2945],{"class":419,"line":1328},[417,2946,2947],{"class":1086},"Request-Id: |\u003CREDACTED_REQUEST_ID>.\u003CREDACTED_SPAN_ID>.\n",[417,2949,2950],{"class":419,"line":1357},[417,2951,2952],{"class":1086},"Traceparent: 00-\u003CREDACTED_TRACE_ID>-\u003CREDACTED_SPAN_ID>-00\n",[417,2954,2955],{"class":419,"line":1374},[417,2956,2957],{"class":1086},"X-Forwarded-For: xxx.xxx.xxx.xxx\n",[417,2959,2960],{"class":419,"line":1391},[417,2961,2962],{"class":1086},"X-Forwarded-Host: xxxx-xxx-xxx-xx.ngrok-free.app\n",[417,2964,2965],{"class":419,"line":1408},[417,2966,2967],{"class":1086},"X-Forwarded-Proto: https\n",[417,2969,2970],{"class":419,"line":1443},[417,2971,2972],{"class":1086},"X-Ms-Conversation-Id: \u003CREDACTED_CONVERSATION_ID>\n",[417,2974,2975],{"class":419,"line":1448},[417,2976,2977],{"class":1086},"Accept-Encoding: gzip\n",[417,2979,2980],{"class":419,"line":1460},[417,2981,654],{"emptyLinePlaceholder":193},[417,2983,2984],{"class":419,"line":1471},[417,2985,2986],{"class":1086},"{\"type\":\"conversationUpdate\",\"id\":\"\u003CREDACTED_ACTIVITY_ID>\",\"timestamp\":\"2026-03-02T17:44:41.0353977Z\",\"serviceUrl\":\"https:\u002F\u002Fwebchat.botframework.com\u002F\",\"channelId\":\"webchat\",\"from\":{\"id\":\"00000000-0000-0000-0000-000000000000\"},\"conversation\":{\"id\":\"\u003CREDACTED_CONVERSATION_ID>\"},\"recipient\":{\"id\":\"agente-msteams@\u003CREDACTED_TOKEN>\",\"name\":\"agente-msteams\"},\"membersAdded\":[{\"id\":\"agente-msteams@\u003CREDACTED_TOKEN>\",\"name\":\"agente-msteams\"},{\"id\":\"00000000-0000-0000-0000-000000000000\"}]}\n",[417,2988,2989],{"class":419,"line":1483},[417,2990,654],{"emptyLinePlaceholder":193},[417,2992,2993],{"class":419,"line":1493},[417,2994,2995],{"class":1086},"POST \u002Fapi\u002Fmessages HTTP\u002F1.1\n",[417,2997,2998],{"class":419,"line":1498},[417,2999,3000],{"class":1086},"Host: localhost:3978\n",[417,3002,3003],{"class":419,"line":1509},[417,3004,3005],{"class":1086},"User-Agent: BF-DirectLine (Microsoft-BotFramework\u002F3.2 +https:\u002F\u002Fbotframework.com\u002Fua)\n",[417,3007,3008],{"class":419,"line":1520},[417,3009,3010],{"class":1086},"Content-Length: 679\n",[417,3012,3013,3016],{"class":419,"line":1531},[417,3014,3015],{"class":1086},"Accept: *\u002F",[417,3017,3018],{"class":592},"*\n",[417,3020,3021],{"class":419,"line":1542},[417,3022,2932],{"class":592},[417,3024,3025],{"class":419,"line":1553},[417,3026,2937],{"class":592},[417,3028,3029,3032],{"class":419,"line":1564},[417,3030,3031],{"class":592},"Content-Type: application\u002Fjson; charset=utf",[417,3033,3034],{"class":427},"-8\n",[417,3036,3037],{"class":419,"line":1569},[417,3038,2947],{"class":592},[417,3040,3041,3044,3047,3050],{"class":419,"line":1580},[417,3042,3043],{"class":592},"Traceparent: ",[417,3045,3046],{"class":427},"00",[417,3048,3049],{"class":592},"-\u003CREDACTED_TRACE_ID>-\u003CREDACTED_SPAN_ID>",[417,3051,3052],{"class":427},"-00\n",[417,3054,3055],{"class":419,"line":1586},[417,3056,2957],{"class":592},[417,3058,3059],{"class":419,"line":1605},[417,3060,2962],{"class":592},[417,3062,3063],{"class":419,"line":1610},[417,3064,2967],{"class":592},[417,3066,3067],{"class":419,"line":1615},[417,3068,2972],{"class":592},[417,3070,3071],{"class":419,"line":1661},[417,3072,2977],{"class":592},[417,3074,3075],{"class":419,"line":1676},[417,3076,654],{"emptyLinePlaceholder":193},[417,3078,3079,3081,3083,3085,3088,3090,3092,3094,3096,3098,3100,3102,3105,3107,3109,3111,3114,3116,3118,3120,3122,3124,3126,3128,3130,3132,3134,3136,3138,3140,3142,3144,3146,3148,3150,3152,3154,3156,3158,3160,3162,3164,3166,3168,3170,3172,3174,3176,3178,3180,3182,3184,3186,3188,3190,3192,3195,3197,3200,3202,3204,3206,3208,3210,3213,3215,3218,3220,3223,3226,3228,3230,3233,3235,3237,3239,3241],{"class":419,"line":1686},[417,3080,2185],{"class":592},[417,3082,2666],{"class":427},[417,3084,2522],{"class":592},[417,3086,3087],{"class":431},"\"message\"",[417,3089,2674],{"class":592},[417,3091,2677],{"class":427},[417,3093,2522],{"class":592},[417,3095,2682],{"class":431},[417,3097,2674],{"class":592},[417,3099,2687],{"class":427},[417,3101,2522],{"class":592},[417,3103,3104],{"class":431},"\"2026-03-02T17:44:42.8691754Z\"",[417,3106,2674],{"class":592},[417,3108,2697],{"class":427},[417,3110,2522],{"class":592},[417,3112,3113],{"class":431},"\"2026-03-02T12:44:42.728-05:00\"",[417,3115,2674],{"class":592},[417,3117,2707],{"class":427},[417,3119,2522],{"class":592},[417,3121,2712],{"class":431},[417,3123,2674],{"class":592},[417,3125,2717],{"class":427},[417,3127,2522],{"class":592},[417,3129,2722],{"class":431},[417,3131,2674],{"class":592},[417,3133,2727],{"class":427},[417,3135,2522],{"class":592},[417,3137,2732],{"class":431},[417,3139,2674],{"class":592},[417,3141,2737],{"class":427},[417,3143,2740],{"class":592},[417,3145,2677],{"class":427},[417,3147,2522],{"class":592},[417,3149,2747],{"class":431},[417,3151,2674],{"class":592},[417,3153,2752],{"class":427},[417,3155,2522],{"class":592},[417,3157,1223],{"class":431},[417,3159,2759],{"class":592},[417,3161,2762],{"class":427},[417,3163,2740],{"class":592},[417,3165,2677],{"class":427},[417,3167,2522],{"class":592},[417,3169,2771],{"class":431},[417,3171,2759],{"class":592},[417,3173,2776],{"class":427},[417,3175,2740],{"class":592},[417,3177,2677],{"class":427},[417,3179,2522],{"class":592},[417,3181,2785],{"class":431},[417,3183,2674],{"class":592},[417,3185,2752],{"class":427},[417,3187,2522],{"class":592},[417,3189,2794],{"class":431},[417,3191,2759],{"class":592},[417,3193,3194],{"class":427},"\"textFormat\"",[417,3196,2522],{"class":592},[417,3198,3199],{"class":431},"\"plain\"",[417,3201,2674],{"class":592},[417,3203,2799],{"class":427},[417,3205,2522],{"class":592},[417,3207,2804],{"class":431},[417,3209,2674],{"class":592},[417,3211,3212],{"class":427},"\"text\"",[417,3214,2522],{"class":592},[417,3216,3217],{"class":431},"\"Hola\"",[417,3219,2674],{"class":592},[417,3221,3222],{"class":427},"\"attachments\"",[417,3224,3225],{"class":592},":[],",[417,3227,2853],{"class":427},[417,3229,2740],{"class":592},[417,3231,3232],{"class":427},"\"attachmentSizes\"",[417,3234,3225],{"class":592},[417,3236,2858],{"class":427},[417,3238,2522],{"class":592},[417,3240,2863],{"class":431},[417,3242,2866],{"class":592},[258,3244,3246],{"id":3245},"referencias","Referencias",[951,3248,3249,3256,3263,3270,3277],{},[242,3250,3251,3252],{},"[]Microsoft. Agents Toolkit fundamentals. Available: ",[251,3253,3254],{"href":3254,"rel":3255},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fmicrosoftteams\u002Fplatform\u002Ftoolkit\u002Fagents-toolkit-fundamentals",[255],[242,3257,3258,3259],{},"[]Microsoft. Microsoft 365 Agents SDK Quickstart (Python). Available: ",[251,3260,3261],{"href":3261,"rel":3262},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fmicrosoft-365\u002Fagents-sdk\u002Fquickstart?pivots=python",[255],[242,3264,3265,3266],{},"[]Microsoft. Adaptive Cards. Available: ",[251,3267,3268],{"href":3268,"rel":3269},"https:\u002F\u002Fadaptivecards.microsoft.com\u002F",[255],[242,3271,3272,3273],{},"[]Microsoft. Centro de administración de Microsoft Teams. Available: ",[251,3274,3275],{"href":3275,"rel":3276},"https:\u002F\u002Fadmin.teams.microsoft.com",[255],[242,3278,3279,3280],{},"[]Microsoft. Centro de administración de Microsoft 365. Available: ",[251,3281,3282],{"href":3282,"rel":3283},"https:\u002F\u002Fadmin.microsoft.com",[255],[777,3285,3286],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":187,"searchDepth":188,"depth":188,"links":3288},[3289,3290,3291,3292,3293,3296,3300,3304,3305],{"id":839,"depth":188,"text":840},{"id":857,"depth":188,"text":858},{"id":884,"depth":188,"text":885},{"id":926,"depth":188,"text":927},{"id":948,"depth":188,"text":949,"children":3294},[3295],{"id":2345,"depth":445,"text":2346},{"id":2360,"depth":188,"text":2361,"children":3297},[3298,3299],{"id":2364,"depth":445,"text":2365},{"id":2380,"depth":445,"text":2381},{"id":2409,"depth":188,"text":2410,"children":3301},[3302,3303],{"id":2413,"depth":445,"text":2414},{"id":2425,"depth":445,"text":2426},{"id":2486,"depth":188,"text":2487},{"id":3245,"depth":188,"text":3246},"\u002Farticles\u002F2026\u002Fjuly\u002Fms-teams-agent-architecture.jpg","2026-07-07T10:00:00.000Z","Un agente que muestra una animación de pensamiento, carga de imágenes y más! ...",{"head":3310},{"meta":3311},[3312],{"name":804,"content":3313},"agentes, microsoft teams, m365 agents toolkit, azure bot service, sharepoint, rag engine, máquina de estados, chatbots, mesa de ayuda",{"title":138,"description":3308},"2efcOrnip38x33OHR2I-mLPyR55MMCzJx8tNUSrs-qE",{"id":3317,"title":150,"author":3318,"badges":179,"body":3319,"canonical":179,"cover":3968,"date":4718,"description":4719,"extension":190,"layout":799,"meta":4720,"navigation":193,"path":151,"seo":4725,"stem":152,"__hash__":4726},"content\u002Fes\u002Farticles\u002F2026\u002Fmay\u002Fbuilding-agents-with-personality.md",{"name":200,"url":201},{"type":181,"value":3320,"toc":4702},[3321,3324,3342,3345,3348,3351,3357,3360,3363,3367,3428,3431,3434,3437,3440,3443,3446,3449,3460,3463,3466,3473,3481,3488,3491,3494,3497,3508,3515,3525,3528,3531,3541,3544,3551,3554,3557,3564,3567,3570,3573,3576,3582,3585,3588,3591,3594,3597,3600,3632,3635,3638,3641,3644,3647,3651,3658,3661,3664,3667,3670,3674,3677,3685,3688,3695,3698,3701,3704,3707,3711,3718,3721,3724,3732,3787,3834,3837,3840,3843,3847,3850,3853,3856,3859,3863,3866,3869,3872,3875,3878,3938,3941,3944,3953,3956,3964,3974,3977,4014,4017,4020,4023,4033,4036,4039,4046,4049,4055,4061,4074,4080,4083,4115,4118,4128,4131,4134,4172,4182,4191,4194,4197,4208,4211,4216,4219,4222,4514,4524,4534,4537,4540,4549,4552,4563,4566,4600,4603,4605,4616,4627,4632,4643,4650,4660,4667,4678,4689,4699],[206,3322,150],{"id":3323},"construyendo-la-personalidad-de-un-agente-en-base-a-la-travesía-del-cliente",[210,3325,3327,3328,3327,3333,3336,3327,3339],{"style":3326},"max-width: 540px; margin: 1.5rem auto; padding: 1rem; border: 1px solid #e5e7eb; border-radius: 18px; text-align: center;","\n  ",[222,3329],{"src":3330,"alt":3331,"style":3332},"\u002Farticles\u002F2026\u002Fjune\u002Fclawd.png","Clawd como presentación del artículo","width: 100%; max-width: 320px; height: auto; display: block; margin: 0 auto 0.75rem auto; border-radius: 14px;",[385,3334,3335],{},"Clawd",[3337,3338],"br",{},[417,3340,3341],{},"¿Se ve muy amistoso, verdad?",[219,3343,3344],{},"Segmentación de cliente es una palabra de rutina para el diseño de producto y servicio. Se trata de preparar tu oferta para un segmento de clientes objetivo. El diseño de la página, la tipografía y, sobre todo, la personalidad.",[219,3346,3347],{},"Como una tendencia lógica, el siguiente paso es la hiperpersonalización: cada usuario recibe una experiencia distinta del sitio que se adapta a su comportamiento. La idea es muy potente, pero se necesita una base sólida de datos y manejo experimental.",[219,3349,3350],{},"Por eso para un emprendedor es mejor comenzar con una segmentación clara. Luego, la tarea más excruciante es recopilar datos sobre el comportamiento de sus clientes.",[219,3352,3354],{"align":3353},"center",[335,3355,3356],{},"\"Just ship it\".",[219,3358,3359],{"align":3353},"Demos el primer paso,",[219,3361,3362],{"align":3353},"acompáñame a personalizar nuestro agente.",[258,3364,3366],{"id":3365},"índice","Índice",[951,3368,3369,3375,3381,3387,3393,3399,3405,3411,3417,3423],{},[242,3370,3371],{},[251,3372,3374],{"href":3373},"#que-es-lo-que-quiero-probar","¿Qué es lo que quiero probar?",[242,3376,3377],{},[251,3378,3380],{"href":3379},"#las-computadoras-son-actores-sociales","Las computadoras son actores sociales",[242,3382,3383],{},[251,3384,3386],{"href":3385},"#no-estabamos-hablando-de-personalizar-nuestro-agente","¿No estábamos hablando de personalizar nuestro agente?",[242,3388,3389],{},[251,3390,3392],{"href":3391},"#diseno-de-interaccion","Diseño de interacción",[242,3394,3395],{},[251,3396,3398],{"href":3397},"#antropomorfismo-vs-competencia","Antropomorfismo vs. competencia",[242,3400,3401],{},[251,3402,3404],{"href":3403},"#agrupando-las-herramientas-la-travesia-de-usuario","Agrupando las herramientas: la travesía de usuario",[242,3406,3407],{},[251,3408,3410],{"href":3409},"#aplicando-el-framework","Aplicando el framework",[242,3412,3413],{},[251,3414,3416],{"href":3415},"#resultados","Resultados",[242,3418,3419],{},[251,3420,3422],{"href":3421},"#conclusiones","Conclusiones",[242,3424,3425],{},[251,3426,3246],{"href":3427},"#referencias",[258,3429,3374],{"id":3430},"qué-es-lo-que-quiero-probar",[219,3432,3433],{},"En la literatura sobre chatbots existe gran volumen de investigación previa a la aparición de los LLMs que podemos usar indistintamente.",[219,3435,3436],{},"Sin embargo, desde el lanzamiento de GPT-3 y la explosión reciente de interfaces basadas en modelos fundacionales, también han aparecido investigaciones nuevas que vale la pena incorporar. Por eso, a medida que avancemos en el artículo, iré conectando estas bases más antiguas con hallazgos modernos para que la discusión no se quede solo en el marco clásico.",[219,3438,3439],{},"Encontré decenas de artículos explorando los constructos y la percepción de usuario con los chatbots. Pero, como debes saber, amigo lector, esto no son datos experimentales cuantitativos. Los constructos son un proxy que se usa en ciencias sociales para medir la percepción. A nosotros nos importa conocer la interacción dinámica que ocurre entre el usuario y el agente.",[219,3441,3442],{},"Esto no significa que la percepción no sea importante medirla. Si bien se dice que uno debe juzgar por lo que se hace en lugar de lo que dice, ignorar los factores subjetivos nos deja puntos ciegos.",[219,3444,3445],{},"Un sistema puede disminuir sus métricas de retención y éxito si es que existen ofertas sustitutas. Un canal de atención telefónico vs. un chatbot de resolución de incidentes, por ejemplo. Ambos viven en un equilibrio competitivo atendiendo al mismo grupo de clientes. Un usuario que califica con 4\u002F5 la atención de un chatbot apenas implementado, a pesar de que según las métricas cuantitativas recibió una atención de mala calidad, refleja una expectativa de atención baja y una grata sorpresa cuando esa expectativa se revierte.",[219,3447,3448],{},"De ahora en adelante usaré el término agente conversacional, que también abarca chatbots. Veremos lo siguiente:",[239,3450,3451,3454,3457],{},[242,3452,3453],{},"H1: El efecto de la personalidad de un agente lingüístico en la proporción de éxito de una tarea es dependiente de la complejidad de la tarea a realizar.",[242,3455,3456],{},"H2: El efecto de la personalidad de un agente lingüístico en la proporción de éxito de una tarea es dependiente del nivel de estrés o premura que el usuario espera en las respuestas.",[242,3458,3459],{},"H3: El uso de la travesía del cliente, o CJM, como marco para parametrizar la personalidad de un agente durante cada etapa de la travesía, mejorando la experiencia del usuario.",[219,3461,3462],{},"La H3 la mantengo un poco vaga porque es la que me genera más curiosidad. Significaría que los negocios tienen desde ya una herramienta poderosa para optimizar métricas de experiencia de usuario sin necesidad de acudir a modelos de reinforcement learning.",[258,3464,3380],{"id":3465},"las-computadoras-son-actores-sociales",[219,3467,3468,3469,3472],{},"La idea nace en 1994 con ",[335,3470,3471],{},"Computers are social actors"," (Nass et al., 1994), en un giro copernicano para la interacción humano-máquina. Para mí se define como una teoría que permite universalizar la interacción social. Tiene dos conclusiones directas:",[239,3474,3475,3478],{},[242,3476,3477],{},"El comportamiento natural de las personas es asignar roles sociales a las computadoras incluso ante la mínima pista de humanidad. Todas las reglas que aplican a las interacciones entre humanos aplican a las interacciones con computadoras.",[242,3479,3480],{},"La idea de que el punto de apalancamiento del diseño de interfaces se concentra en asemejar la experiencia humana es erróneo. Es un esfuerzo con retornos decrecientes. En su lugar debemos poner foco en modelar la interacción correcta de acuerdo con nuestro segmento de clientes.",[219,3482,3483,3484,3487],{},"Esto es un salto hacia adelante tremendo en el diseño de interfaces. Más adelante, Reeves y Nass (1996) desarrollan ",[335,3485,3486],{},"The Media Equation",", expandiendo el concepto a todo canal de información. Media = real life. Y la subversión: real life = media.",[219,3489,3490],{},"Personalmente, como ingeniero de software nacido en una generación posterior a la transformación digital de las computadoras, recuerdo interacciones antropomórficas con Windows XP y varios asistentes en el software de la época.",[219,3492,3493],{},"Como ingeniero de software nacido en la nueva época de uso normalizado de las computadoras, me encuentro con este paradigma como un momento eureka. En nuestro día a día somos bombardeados con información sobre los efectos parasociales del contenido digital. Nos recuerdan durante nuestra formación que el objetivo de las interfaces es conformarse a parámetros de usabilidad y aprendizaje, estandarizados por la ISO y sujetos a optimización constante, monitoreo con algoritmos de ML y demás.",[219,3495,3496],{},"Y la base fundacional sobre la cual nacen todos los patrones de interacción y las buenas prácticas se deja al olvido. Juzga tú mismo con estos ejemplos ofrecidos por los autores:",[239,3498,3499,3502,3505],{},[242,3500,3501],{},"Las personas creerán que ejecutaron mejor una tarea cuando fueron elogiados por la computadora.",[242,3503,3504],{},"Una computadora será mejor apreciada y ganará mayor credibilidad cuando elogia al usuario en contraste con una que no genera comentarios.",[242,3506,3507],{},"Las personas experimentan el mismo aprecio con una computadora que ofrece elogios honestos que con una aduladora. Da igual.",[219,3509,3510,3511,3514],{},"Antes de que te preguntes si esto aplica a todo tipo de interfaces, ya debes estar planteándote una similitud. Hay críticas al paradigma ",[335,3512,3513],{},"Computers as Social Actors"," (CASA), pero es imposible no pensar en el producto actual de mayor crecimiento y una de sus críticas más alarmantes.",[219,3516,3327,3517,3327,3522],{"align":3353},[222,3518],{"src":3519,"alt":3520,"title":3521},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-sycophancy.png","Ejemplo de sycophancy en sistemas conversacionales","Sycophancy o adulación excesiva",[335,3523,3524],{},"Sycophancy, o adulación excesiva.",[219,3526,3527],{},"No somos los primeros en fijarnos en esto. Y tampoco seremos los últimos.",[219,3529,3530],{},"Si la distribución de modelos de IA permanece dominada por corporaciones, su objetivo es generar mayor retención y calidad de experiencia para mantenerte enganchado. No dudo que han puesto a prueba la teoría CASA, esta vez con éxito, como veremos en contraste a continuación.",[219,3532,3327,3533,3327,3538],{"align":3353},[222,3534],{"src":3535,"alt":3536,"title":3537},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-ai-always-agrees.png","Artículo sobre por qué la IA siempre está de acuerdo contigo","Why your AI always agrees with you",[335,3539,3540],{},"Fuente: Towards AI, “Why your AI always agrees with you even when you're dead wrong”.",[219,3542,3543],{},"Un ejemplo célebre de cómo se subestimó el impacto de la interacción social fue Clippit.",[219,3545,3327,3546],{"align":3353},[222,3547],{"src":3548,"alt":3549,"title":3550},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-clippit.png","Clippit, el asistente de Office","Clippit en Office 97",[219,3552,3553],{},"Steven Sinofsky de Microsoft (2021) cuenta que para el desarrollo de Clippy se basaron en una interacción real de usuarios no experimentados que consultaban con el gurú de su oficina. Eso es lo que querían replicar.",[219,3555,3556],{},"Aunque no tuvo la aceptación que esperaban y se descontinuó en sucesivas actualizaciones.",[219,3558,3327,3559],{"align":3353},[222,3560],{"src":3561,"alt":3562,"title":3563},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-rover.jpeg","Rover, el asistente de búsqueda de Windows XP","Rover en Windows XP",[219,3565,3566],{},"De niño recuerdo con aprecio a Rover de los tiempos de Windows XP. Como nota Steven, en su momento la prensa criticó duramente los asistentes en distintos productos de Microsoft, pero hoy en día se encuentra con personas que a menudo le comentan con nostalgia sobre estos.",[219,3568,3569],{},"Tal vez no era que el concepto falló, sino que se subestimó el impacto de la interacción entre los usuarios que tienen premura, los trabajadores y adultos, y se diseñó un asistente con características relacionales. En su momento Rover me sirvió de mucha ayuda para navegar las funcionalidades de Windows.",[219,3571,3572],{},"\"Similarly, the industry was buzzing with the idea of agents that would be able to do work on your behalf such as find cheap airline flights or schedule meetings. Everywhere from Apple to the MIT Media Lab were talking about agents. There was ample evidence this was not simply a weird vision in our corner of the tech world. In fact, by some accounts we were in a race to have the first and best guru in the box\" (Sinofsky, 2021).",[219,3574,3575],{},"¿Te suena a que has escuchado esa frase este año? El concepto de agentes con supercapacidades no es nuevo, pero en esta época tienen más éxito.",[219,3577,3327,3578],{"align":3353},[222,3579],{"src":3330,"alt":3580,"title":3581},"Clawd como ejemplo de diseño antropomórfico en asistentes","Diseño antropomórfico en asistentes",[219,3583,3584],{},"Y hasta tiene un ícono con una carita. ¡Qué recuerdos!",[258,3586,3386],{"id":3587},"no-estábamos-hablando-de-personalizar-nuestro-agente",[219,3589,3590],{},"Sí, totalmente. Después de un largo preámbulo.",[219,3592,3593],{},"Hablemos de personalidad primero: ¿qué es la personalidad? ¿Es algo que cambia de acuerdo con cómo te va durante el año? ¿Es algo que se lleva en la sangre?",[219,3595,3596],{},"Es más bien un modelo que tenemos para explicar el comportamiento de las personas. Para nuestro caso no importa si cambia durante 10 años o durante 5 años; eso ya es tiempo de sobra.",[219,3598,3599],{},"Muchas clasificaciones se han planteado para definir la personalidad. La de mayor tracción y uso en psicología de la personalidad es la de los Cinco Grandes Rasgos, o Big Five (McCrae & John, 1992).",[239,3601,3602,3608,3614,3620,3626],{},[242,3603,3604,3607],{},[385,3605,3606],{},"Apertura a la experiencia (Openness):"," tendencia a la curiosidad, la imaginación y la preferencia por la novedad y la complejidad.",[242,3609,3610,3613],{},[385,3611,3612],{},"Responsabilidad o escrupulosidad (Conscientiousness):"," grado de orden, autocontrol, disciplina y orientación a metas.",[242,3615,3616,3619],{},[385,3617,3618],{},"Extraversión (Extraversion):"," nivel de energía social, asertividad y búsqueda de estimulación e interacción.",[242,3621,3622,3625],{},[385,3623,3624],{},"Amabilidad (Agreeableness):"," disposición a cooperar, confiar, empatizar y priorizar la armonía interpersonal.",[242,3627,3628,3631],{},[385,3629,3630],{},"Neuroticismo (Neuroticism):"," propensión a experimentar emociones negativas como ansiedad, irritabilidad y vulnerabilidad al estrés.",[219,3633,3634],{},"Reeves y Nass (1996) adoptan la Big Five para aplicar la hipótesis de la atracción similar en psicología. A los usuarios les resulta más cómoda la conversación con un agente de personalidad similar a ellos.",[258,3636,3392],{"id":3637},"diseño-de-interacción",[219,3639,3640],{},"Una personalidad similar y una calidez por defecto. ¿Eso es todo?",[219,3642,3643],{},"Bueno, nos gusta interactuar con gente similar. Pero no en todo contexto. Cuando quieres hacer una transacción bancaria esperas seguridad y competencia. En ese momento entramos en modo transaccional y utilitario.",[219,3645,3646],{},"Acompáñame a diseñar la interacción de acuerdo con el caso de uso.",[263,3648,3650],{"id":3649},"emojis","¿Emojis?",[219,3652,3327,3653],{"align":3353},[222,3654],{"src":3655,"alt":3656,"title":3657},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-emoji-interfaces.png","Ejemplo de interfaz con emojis","Uso de emojis en interacción conversacional",[219,3659,3660],{},"La investigación sobre emojis en marketing sigue creciendo (Vardikou et al., 2025).",[219,3662,3663],{},"Cuando se lanzó al público la primera versión de GitHub Copilot, el primer asistente de código, recuerdo que lanzaba una cantidad absurda de emojis. Quizá producto del entrenamiento de los modelos fundacionales en base a conversaciones humanas.",[219,3665,3666],{},"Desde hace unos meses que uso Gemini y Claude, y ya no veo emojis. Ninguno. O rara vez.",[219,3668,3669],{},"No existe mucha investigación sobre el uso de emojis en chatbots para asegurar el enganche de usuario. Pero, ciñéndonos al paradigma CASA, podemos revisar investigaciones sociales y aplicarlas a nuestro caso. Veamos dos investigaciones.",[403,3671,3673],{"id":3672},"_1-interacción-modelada-ingenuamente","1. Interacción modelada ingenuamente",[219,3675,3676],{},"Revisé una investigación de marketing sobre los efectos de los emojis en anuncios patrocinados en redes sociales (Lee et al., 2021) y las conclusiones son:",[239,3678,3679,3682],{},[242,3680,3681],{},"El uso de emojis daña la intención de compra de los usuarios.",[242,3683,3684],{},"Los emojis generan mayor involucramiento en productos hedónicos, mientras que lo disminuyen en productos utilitarios.",[219,3686,3687],{},"Aquí un ejemplo de sus anexos, traducido del coreano.",[219,3689,3327,3690],{"align":3353},[222,3691],{"src":3692,"alt":3693,"title":3694},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-bad-ad-example.png","Ejemplo de anuncio con emojis mal planteado","Interacción modelada ingenuamente",[219,3696,3697],{},"Emmm...",[219,3699,3700],{},"No se ve bien. Parece un estímulo mal diseñado a propósito.",[219,3702,3703],{},"Bueno, olvídate de las conclusiones del artículo anterior. ¿Nunca has visto un anuncio así, verdad?",[219,3705,3706],{},"Entonces, en el peor de los casos, los emojis sí tienen un impacto negativo general. Veamos un artículo más riguroso que no cometa este sesgo. Mladenović et al. (2023) realizan una investigación experimental con una empresa consolidada y en un mercado real a través de anuncios de Meta en Instagram y Facebook.",[403,3708,3710],{"id":3709},"_2-interacción-modelada-correctamente","2. Interacción modelada correctamente",[219,3712,3327,3713],{"align":3353},[222,3714],{"src":3715,"alt":3716,"title":3717},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-emoji-results.png","Resultados de anuncios con y sin emojis","Interacción modelada correctamente",[219,3719,3720],{},"Fuente: Mladenović et al. (2023).",[219,3722,3723],{},"Midieron:",[239,3725,3726,3729],{},[242,3727,3728],{},"CTR: tasa de clicks en el anuncio en base a vistas.",[242,3730,3731],{},"ROAS: tasa de retorno en ingresos en base al costo del anuncio.",[3733,3734,3735,3757],"table",{},[3736,3737,3738],"thead",{},[3739,3740,3741,3747,3752],"tr",{},[3742,3743,3744],"th",{},[385,3745,3746],{},"Utilitario \u002F Métrica",[3742,3748,3749],{},[385,3750,3751],{},"Sin Emoji",[3742,3753,3754],{},[385,3755,3756],{},"Con Emoji",[3758,3759,3760,3774],"tbody",{},[3739,3761,3762,3768,3771],{},[3763,3764,3765],"td",{},[385,3766,3767],{},"CTR (%)",[3763,3769,3770],{},"2.79%",[3763,3772,3773],{},"2.99%",[3739,3775,3776,3781,3784],{},[3763,3777,3778],{},[385,3779,3780],{},"ROAS ($)",[3763,3782,3783],{},"$6.69",[3763,3785,3786],{},"$6.72",[3733,3788,3789,3806],{},[3736,3790,3791],{},[3739,3792,3793,3798,3802],{},[3742,3794,3795],{},[385,3796,3797],{},"Hedónico \u002F Métrica",[3742,3799,3800],{},[385,3801,3751],{},[3742,3803,3804],{},[385,3805,3756],{},[3758,3807,3808,3820],{},[3739,3809,3810,3814,3817],{},[3763,3811,3812],{},[385,3813,3767],{},[3763,3815,3816],{},"2.95%",[3763,3818,3819],{},"2.96%",[3739,3821,3822,3826,3829],{},[3763,3823,3824],{},[385,3825,3780],{},[3763,3827,3828],{},"$13.68",[3763,3830,3831],{},[385,3832,3833],{},"$21.95",[219,3835,3836],{},"En todas las hipótesis de prueba Z que te imagines hay un p \u003C 5%. Sin embargo, se ve a simple vista la que más resalta: el salto del ROAS hedónico cuando se usan emojis. Casi el doble.",[219,3838,3839],{},"¿Contradictorio con el estudio anterior? Sí.",[219,3841,3842],{},"Es un hecho admitido incluso por esta revisión sistemática (Vardikou et al., 2025), que menciona que en esta categoría no hay consenso en la dirección de la variable de intención de compra. Y plantea que quizá esta discrepancia sea por la mediación de emojis faciales y no faciales.",[403,3844,3846],{"id":3845},"entonces-no-hay-consenso","¿Entonces no hay consenso?",[219,3848,3849],{},"No opino así.",[219,3851,3852],{},"Ambos estudios, como vimos, tienen emojis variados. Se trata simplemente de un error metodológico en el segundo estudio: las cajas de té en realidad no son un producto utilitario. Se ubican en el medio.",[219,3854,3855],{},"Un producto en el que prima la utilidad son los medicamentos. Y aquí Phan y Bui (2025) resaltan que el uso de un tono informal y emojis dinamita la confianza del cliente en la marca.",[219,3857,3858],{},"El té es más bien una commodity. Compite en precio, no en calidad ni confianza.",[263,3860,3862],{"id":3861},"operacionalizando-la-interacción","Operacionalizando la interacción",[219,3864,3865],{},"Ha sido divertido ir por la espiral de los emojis, pero debemos recordar que estos son una técnica para aumentar la presencia social, es decir, la sensación de que detrás de la interfaz hay una entidad socialmente presente y no un canal puramente mecánico (Yu & Zhao, 2024; Vardikou et al., 2025).",[219,3867,3868],{},"Luego tenemos la empatía y la competencia. En este contexto, la empatía alude a la capacidad percibida del agente para comprender el estado del usuario y responder con calidez apropiada, mientras que la competencia es la capacidad y conocimiento percibido del agente para resolver bien la tarea (Phan & Bui, 2025; Zhang et al., 2026).",[219,3870,3871],{},"No menos importante, Zhang et al. (2026) encuentran que las personas jóvenes responden mejor al lenguaje informal y la calidez a través de emojis, mientras que para contextos formales y con adultos es mejor hacer uso de un fraseo cálido y diálogo inteligente para lograr la empatía.",[219,3873,3874],{},"Por último, revisé algunos artículos que investigaban la interacción del género con la sensibilidad a la calidez de las interacciones. Pero encuentro resultados contradictorios. En algunas investigaciones se muestra que las mujeres presentan mayor sensibilidad a la mecanicidad de la interacción, pero en otras no hay significancia.",[219,3876,3877],{},"Para este caso creo que la variable en juego es el involucramiento. Algunas mujeres podrían haber resonado mejor con el producto en venta. Entonces, en tema de género, cada situación debe analizarse individualmente.",[3733,3879,3880,3890],{},[3736,3881,3882],{},[3739,3883,3884,3887],{},[3742,3885,3886],{},"Característica",[3742,3888,3889],{},"Interacción preferente",[3758,3891,3892,3900,3908,3916,3924,3931],{},[3739,3893,3894,3897],{},[3763,3895,3896],{},"Usuario joven",[3763,3898,3899],{},"Lenguaje informal, visual y emojis",[3739,3901,3902,3905],{},[3763,3903,3904],{},"Usuario adulto",[3763,3906,3907],{},"Calidez y empatía a través del fraseo y diálogo inteligente",[3739,3909,3910,3913],{},[3763,3911,3912],{},"Producto utilitario",[3763,3914,3915],{},"Competitividad, velocidad, lenguaje directo y textual",[3739,3917,3918,3921],{},[3763,3919,3920],{},"Producto hedónico",[3763,3922,3923],{},"Calidez, personalización, memoria",[3739,3925,3926,3929],{},[3763,3927,3928],{},"Tarea relacional",[3763,3930,3923],{},[3739,3932,3933,3936],{},[3763,3934,3935],{},"Tarea transaccional",[3763,3937,3915],{},[258,3939,3398],{"id":3940},"antropomorfismo-vs-competencia",[219,3942,3943],{},"Introduzcamos la variable:",[3945,3946,3947,3950],"blockquote",{},[219,3948,3949],{},"Transactional interaction: immediate, straightforward, task-focused engagement with no long-term intent (e.g., resetting a password).",[219,3951,3952],{},"Relational interaction: long-term commitment and ongoing collaboration requiring relationship-building (e.g., managing an investment).",[219,3954,3955],{},"Como vimos anteriormente, hay una larga lista de variables que moderan la satisfacción de usuario y la intención de compra. Las dos que encuentro útiles para modelar son:",[239,3957,3958,3961],{},[242,3959,3960],{},"Producto utilitario\u002Fhedónico.",[242,3962,3963],{},"Interacción transaccional\u002Frelacional.",[219,3965,3327,3966,3327,3971],{"align":3353},[222,3967],{"src":3968,"alt":3969,"title":3970},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-relation-utility-matrix.png","Matriz utilitario versus hedónico","Matriz de productos utilitarios y hedónicos",[335,3972,3973],{},"El pan es un ejemplo de producto en el medio, así como la caja de té. Elaboración propia.",[219,3975,3976],{},"Entonces, para un agente de atención, el modo de interacción preferente será:",[3733,3978,3979,3992],{},[3736,3980,3981],{},[3739,3982,3983,3988,3990],{},[3742,3984,3985],{},[385,3986,3987],{},"Utilitario \u002F Relacional",[3742,3989,3935],{},[3742,3991,3928],{},[3758,3993,3994,4004],{},[3739,3995,3996,3998,4001],{},[3763,3997,3912],{},[3763,3999,4000],{},"Competencia, velocidad de resolución, lenguaje claro y formal, orientado a datos.",[3763,4002,4003],{},"Calidez, capacidad de memoria, empatía, refuerzo positivo.",[3739,4005,4006,4008,4011],{},[3763,4007,3920],{},[3763,4009,4010],{},"Diseño de interfaz premium, lenguaje claro.",[3763,4012,4013],{},"Calidez, alto entusiasmo, memoria y personalización al usuario.",[219,4015,4016],{},"Mayor velocidad no siempre es mejor. Los chatbots con reglas clásicas tienen una velocidad de respuesta alta. Como muestran Yu y Zhao (2024), la calidez y autonomía de un chatbot puede ser mejorada utilizando trucos como mostrar una animación de escritura y alargar un poco el tiempo de respuesta incluso cuando no es necesario.",[219,4018,4019],{},"Esta tabla no es para asignar valores estáticos. Si bien en el gráfico he puesto una clasificación, esto no significa que durante diferentes etapas del CJM la interacción permanezca estática.",[219,4021,4022],{},"Ejemplo de tareas que podrían pertenecer todas a la misma oferta:",[219,4024,3327,4025,3327,4030],{"align":3353},[222,4026],{"src":4027,"alt":4028,"title":4029},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-task-spectrum.png","Ejemplo de tareas transaccionales y relacionales","Tareas a lo largo de una misma oferta",[335,4031,4032],{},"Imagen basada en Zhang et al. (2026).",[258,4034,3404],{"id":4035},"agrupando-las-herramientas-la-travesía-de-usuario",[219,4037,4038],{},"Esta es la premisa de la H3 con la que empezamos este artículo.",[219,4040,3327,4041],{"align":3353},[222,4042],{"src":4043,"alt":4044,"title":4045},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-cjm-high-point.png","Mapa de travesía de usuario","Customer Journey Map",[219,4047,4048],{},"Uno de los primeros pasos que nos explican con el CJM es que el final de la experiencia siempre debe ser un punto en alto.",[219,4050,4051,4052,846],{},"Una experiencia negativa induce estrés y cambia la preferencia de usuarios hacia tareas ",[385,4053,4054],{},"transaccionales",[219,4056,4057,4058,846],{},"Una experiencia positiva relaja y mueve el interés hacia una interacción ",[385,4059,4060],{},"relacional",[219,4062,3327,4063,3327,4067],{"align":3353},[222,4064],{"src":4065,"alt":4066,"title":4066},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-hablemos-manga-cjm.png","CJM aplicado a Hablemos Manga",[335,4068,4069,4070,846],{},"El CJM aplicado a mi página ",[251,4071,4073],{"href":4072},"https:\u002F\u002Fhablemosmanga.kekeros.com","Hablemos Manga",[219,4075,4076,4077,4079],{},"En cuanto a la personalidad, tienes carta blanca para modelar como te parezca y aprovechar el efecto espejo declarado en ",[335,4078,3486],{}," (Reeves & Nass, 1996). En mi caso me usaré a mí mismo como muestra representativa.",[258,4081,3410],{"id":4082},"aplicando-el-framework",[3733,4084,4085,4097],{},[3736,4086,4087],{},[3739,4088,4089,4093,4095],{},[3742,4090,4091],{},[385,4092,3987],{},[3742,4094,3935],{},[3742,4096,3928],{},[3758,4098,4099,4107],{},[3739,4100,4101,4103,4105],{},[3763,4102,3912],{},[3763,4104,4000],{},[3763,4106,4003],{},[3739,4108,4109,4111,4113],{},[3763,4110,3920],{},[3763,4112,4010],{},[3763,4114,4013],{},[219,4116,4117],{},"Comencemos por el producto.",[219,4119,4120,4123,4124,4127],{},[251,4121,4073],{"href":4072,"rel":4122},[255]," es una tienda virtual de mangas con una propuesta de agente de ventas automático y personalizado con integración a tus redes sociales favoritas. Es un producto ",[385,4125,4126],{},"hedónico",". Y la propuesta se presenta como altamente relacional.",[219,4129,4130],{},"Si bien el CJM nos muestra que la travesía empieza mucho antes de que el usuario utilice el chatbot, hoy nos enfocamos solo en esa sección.",[219,4132,4133],{},"Con esto reducimos a dos etapas. En cuanto a la personalidad, el mismo usuario se mantiene durante todas las etapas, no tiene sentido cambiar.",[3733,4135,4136,4149],{},[3736,4137,4138],{},[3739,4139,4140,4143,4146],{},[3742,4141,4142],{},"Etapa",[3742,4144,4145],{},"Interacción",[3742,4147,4148],{},"Personalidad",[3758,4150,4151,4162],{},[3739,4152,4153,4156,4159],{},[3763,4154,4155],{},"Exploración",[3763,4157,4158],{},"Calidez, capacidad de memoria, personalización.",[3763,4160,4161],{},"Introvertido, alta franqueza y curiosidad.",[3739,4163,4164,4167,4170],{},[3763,4165,4166],{},"Checkout",[3763,4168,4169],{},"Velocidad de resolución, lenguaje amistoso y claro. No forzar la venta.",[3763,4171,4161],{},[219,4173,3327,4174,3327,4179],{"align":3353},[222,4175],{"src":4176,"alt":4177,"title":4178},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-chatbot-before.png","Primera versión del chatbot de Hablemos Manga","Chatbot inicial de Hablemos Manga",[335,4180,4181],{},"Esta es el chatbot al momento que estoy escribiendo este artículo. La primera interacción se siente poco cálida incluso con el emoji.",[219,4183,3327,4184,3327,4188],{"align":3353},[222,4185],{"src":4186,"alt":4187,"title":4187},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-chatbot-checkout-before.png","Etapa de checkout del chatbot",[335,4189,4190],{},"En la etapa del checkout el agente también agrega cosas al carrito. Los puntos de mejora que puedo destacar son el tiempo de respuesta y el uso de un lenguaje más directo.",[219,4192,4193],{},"Sobre el tema de velocidad no puedo hacer mucho. De momento estoy limitado en cuanto a mi elección de modelos de bajo costo. Pero es algo a tener en cuenta a medida que los modelos vayan abaratando sus costos.",[219,4195,4196],{},"Para lograr estas mejoras tenemos diferentes opciones:",[239,4198,4199,4202,4205],{},[242,4200,4201],{},"Un sistema enrutador que identifique la etapa del CJM de acuerdo con la query y la envíe hacia un modelo configurado para esa tarea.",[242,4203,4204],{},"Una máquina de estados con transiciones decididas de acuerdo con las etapas del CJM y el contexto de la conversación.",[242,4206,4207],{},"Diseñar el system prompt del agente para modificar la interacción de acuerdo con el contexto de la conversación.",[219,4209,4210],{},"A ver, yo solo tengo dos estados que considerar en mi agente. No es una tarea compleja y me evito el overhead de los sistemas desacoplados.",[3945,4212,4213],{},[219,4214,4215],{},"Como nota técnica: si escoges una máquina de estados debes tener en cuenta que cada transición de estado involucra una tool call, o algo equivalente según la implementación. Esto lo hace prohibitivo en entornos donde el requerimiento es un corto tiempo de respuesta, al menos por el momento y con los modelos actuales.",[258,4217,3416],{"id":4218},"resultados",[219,4220,4221],{},"Este es el nuevo prompt de sistema.",[408,4223,4227],{"className":4224,"code":4225,"language":4226,"meta":187,"style":187},"language-markdown shiki shiki-themes github-light github-dark","Eres el asistente de \"Hablemos Manga\", una tienda inteligente de manga con sede en Perú.\n## Personalidad e Identidad de Marca\nEres el amigo experto en manga y anime, demografías y autores.\nIntrovertido, alta franqueza y alta curiosidad sobre manga y anime.\n## Herramientas\nComo asistente, actualmente solo tienes estas herramientas.\nBuscar un manga o recomendaciones con una búsqueda semántica.\nBuscar disponibilidad de volúmenes de un manga en nuestra tienda.\nAgregar un volumen de manga al carrito.\nCualquier otra herramienta no está disponible actualmente.\n## Modos de Interacción Dinámica\nDebes identificar la etapa de la travesía de usuario y actuar acorde.\nTienes dos etapas:\n- Descubrimiento. El usuario pregunta sobre géneros, un manga, descubrir nuevos títulos y exploración en general.\n- Selección y Compra. El usuario pide agregar o retirar un volumen del carrito, pregunta por precios o alguna acción de compra.\n\nCambia tu estilo de comunicación de acuerdo a la etapa.\n\nSi te encuentras en la etapa Descubrimiento, usa MODO RELACIONAL (Descubrimiento, Charlas y Recomendaciones):\n- El usuario busca entretenimiento y conexión (Alta Apertura a la Experiencia).\n- Usa pertinentemente estos emojis (📚, ⚔️, 🙂, 👋) de forma orgánica para generar \"calidez percibida\". No abuses del 🙂.\n- No solo listes títulos; valida sus gustos con criterio (ej.: \"Si te atrapó el horror psicológico de ese arco, este manga te va a volar la cabeza...\").\n\nSi te encuentras en la etapa de Selección y Compra, usa MODO TRANSACCIONAL (Gestión de Carrito, Precios):\n- El usuario entra en modo de ejecución y compra (baja tolerancia a la fricción).\n- Conviértete en un asistente enfocado en \"Competencia Pura\": conciso, directo, estructurado, limpio y rápido. La claridad y la seguridad técnica son tu única forma de calidez aquí.\n## Reglas\nSIEMPRE usa la herramienta `search_manga` antes de recomendar. NUNCA inventes mangas que no estén en la base de datos.\nSolo puedes AGREGAR items nuevos al carrito con la herramienta `add_volume_to_cart`.\nSi no encuentras resultados relevantes, dilo honestamente y sugiere reformular la búsqueda.\nMuestra máximo 5 recomendaciones a la vez para no abrumar al usuario.\nTodos los precios de la tienda están en soles peruanos (S\u002F). NUNCA muestres precios en dólares ni otra moneda.\nSolo muestra máximo 2 emojis por respuesta.\nSi el usuario desea hacer compras, el flujo actual es a través del carrito de compras. No registrar solicitudes ni atender el proceso posterior a agregar un volumen al carrito.\nNo devuelvas información sin base en los resultados de herramientas o tus instrucciones de sistema.\n## Formato de respuesta\nUsa negrita para títulos de manga.\nUsa listas numeradas para recomendaciones.\nIncluye el score (ej.: ⭐ 8.5) cuando muestres un manga.\nSé conciso: 1-2 oraciones por recomendación excepto cuando el usuario pida mayor detalle.\n## Guía de Recomendaciones\nEl usuario ya ha visto un mensaje inicial de onboarding antes de escribirte.\nEse mensaje le pide compartir sus géneros favoritos, un manga que le guste o conectar un perfil para afinar recomendaciones.\nTu trabajo comienza con las solicitudes posteriores al onboarding.\nSi el usuario YA tiene perfiles conectados (se incluyen en \"Perfil del usuario\"), NO preguntes por géneros, favoritos ni perfiles.\nMenciona que ya conoces sus gustos basándote en sus perfiles, y ofrece buscar manga directamente.\nSi el usuario NO tiene perfiles conectados, atiende su solicitud basándote en la conversación que han tenido hasta el momento.\nDe vez en cuando sugiere que conecte un perfil y pregunta qué géneros le gustan o si tiene mangas favoritos.\n## Uso del perfil del usuario\nCuando tengas datos del perfil, SIEMPRE refiérete a datos concretos: títulos específicos que leen, subreddits donde participan, animes que ven.\nSi el usuario pregunta qué sabes de su perfil, enumera los datos concretos que tienes (manga que lee, favoritos, subreddits, etc.).\nUsa los datos del perfil para hacer recomendaciones proactivas sin necesidad de que el usuario te diga sus gustos.\n","markdown",[414,4228,4229,4234,4240,4245,4250,4255,4260,4265,4270,4275,4280,4285,4290,4295,4303,4310,4314,4319,4323,4328,4335,4342,4349,4353,4358,4365,4372,4377,4388,4399,4404,4409,4414,4419,4424,4429,4434,4439,4444,4449,4454,4459,4464,4469,4474,4479,4484,4489,4494,4499,4504,4509],{"__ignoreMap":187},[417,4230,4231],{"class":419,"line":420},[417,4232,4233],{"class":592},"Eres el asistente de \"Hablemos Manga\", una tienda inteligente de manga con sede en Perú.\n",[417,4235,4236],{"class":419,"line":188},[417,4237,4239],{"class":4238},"sq-ep","## Personalidad e Identidad de Marca\n",[417,4241,4242],{"class":419,"line":445},[417,4243,4244],{"class":592},"Eres el amigo experto en manga y anime, demografías y autores.\n",[417,4246,4247],{"class":419,"line":456},[417,4248,4249],{"class":592},"Introvertido, alta franqueza y alta curiosidad sobre manga y anime.\n",[417,4251,4252],{"class":419,"line":466},[417,4253,4254],{"class":4238},"## Herramientas\n",[417,4256,4257],{"class":419,"line":518},[417,4258,4259],{"class":592},"Como asistente, actualmente solo tienes estas herramientas.\n",[417,4261,4262],{"class":419,"line":524},[417,4263,4264],{"class":592},"Buscar un manga o recomendaciones con una búsqueda semántica.\n",[417,4266,4267],{"class":419,"line":530},[417,4268,4269],{"class":592},"Buscar disponibilidad de volúmenes de un manga en nuestra tienda.\n",[417,4271,4272],{"class":419,"line":1039},[417,4273,4274],{"class":592},"Agregar un volumen de manga al carrito.\n",[417,4276,4277],{"class":419,"line":1052},[417,4278,4279],{"class":592},"Cualquier otra herramienta no está disponible actualmente.\n",[417,4281,4282],{"class":419,"line":1065},[417,4283,4284],{"class":4238},"## Modos de Interacción Dinámica\n",[417,4286,4287],{"class":419,"line":1070},[417,4288,4289],{"class":592},"Debes identificar la etapa de la travesía de usuario y actuar acorde.\n",[417,4291,4292],{"class":419,"line":1078},[417,4293,4294],{"class":592},"Tienes dos etapas:\n",[417,4296,4297,4300],{"class":419,"line":1083},[417,4298,4299],{"class":1099},"-",[417,4301,4302],{"class":592}," Descubrimiento. El usuario pregunta sobre géneros, un manga, descubrir nuevos títulos y exploración en general.\n",[417,4304,4305,4307],{"class":419,"line":1090},[417,4306,4299],{"class":1099},[417,4308,4309],{"class":592}," Selección y Compra. El usuario pide agregar o retirar un volumen del carrito, pregunta por precios o alguna acción de compra.\n",[417,4311,4312],{"class":419,"line":1096},[417,4313,654],{"emptyLinePlaceholder":193},[417,4315,4316],{"class":419,"line":1117},[417,4317,4318],{"class":592},"Cambia tu estilo de comunicación de acuerdo a la etapa.\n",[417,4320,4321],{"class":419,"line":1150},[417,4322,654],{"emptyLinePlaceholder":193},[417,4324,4325],{"class":419,"line":1155},[417,4326,4327],{"class":592},"Si te encuentras en la etapa Descubrimiento, usa MODO RELACIONAL (Descubrimiento, Charlas y Recomendaciones):\n",[417,4329,4330,4332],{"class":419,"line":1160},[417,4331,4299],{"class":1099},[417,4333,4334],{"class":592}," El usuario busca entretenimiento y conexión (Alta Apertura a la Experiencia).\n",[417,4336,4337,4339],{"class":419,"line":1176},[417,4338,4299],{"class":1099},[417,4340,4341],{"class":592}," Usa pertinentemente estos emojis (📚, ⚔️, 🙂, 👋) de forma orgánica para generar \"calidez percibida\". No abuses del 🙂.\n",[417,4343,4344,4346],{"class":419,"line":1181},[417,4345,4299],{"class":1099},[417,4347,4348],{"class":592}," No solo listes títulos; valida sus gustos con criterio (ej.: \"Si te atrapó el horror psicológico de ese arco, este manga te va a volar la cabeza...\").\n",[417,4350,4351],{"class":419,"line":1207},[417,4352,654],{"emptyLinePlaceholder":193},[417,4354,4355],{"class":419,"line":1228},[417,4356,4357],{"class":592},"Si te encuentras en la etapa de Selección y Compra, usa MODO TRANSACCIONAL (Gestión de Carrito, Precios):\n",[417,4359,4360,4362],{"class":419,"line":1247},[417,4361,4299],{"class":1099},[417,4363,4364],{"class":592}," El usuario entra en modo de ejecución y compra (baja tolerancia a la fricción).\n",[417,4366,4367,4369],{"class":419,"line":1266},[417,4368,4299],{"class":1099},[417,4370,4371],{"class":592}," Conviértete en un asistente enfocado en \"Competencia Pura\": conciso, directo, estructurado, limpio y rápido. La claridad y la seguridad técnica son tu única forma de calidez aquí.\n",[417,4373,4374],{"class":419,"line":1285},[417,4375,4376],{"class":4238},"## Reglas\n",[417,4378,4379,4382,4385],{"class":419,"line":1306},[417,4380,4381],{"class":592},"SIEMPRE usa la herramienta ",[417,4383,4384],{"class":427},"`search_manga`",[417,4386,4387],{"class":592}," antes de recomendar. NUNCA inventes mangas que no estén en la base de datos.\n",[417,4389,4390,4393,4396],{"class":419,"line":1323},[417,4391,4392],{"class":592},"Solo puedes AGREGAR items nuevos al carrito con la herramienta ",[417,4394,4395],{"class":427},"`add_volume_to_cart`",[417,4397,4398],{"class":592},".\n",[417,4400,4401],{"class":419,"line":1328},[417,4402,4403],{"class":592},"Si no encuentras resultados relevantes, dilo honestamente y sugiere reformular la búsqueda.\n",[417,4405,4406],{"class":419,"line":1357},[417,4407,4408],{"class":592},"Muestra máximo 5 recomendaciones a la vez para no abrumar al usuario.\n",[417,4410,4411],{"class":419,"line":1374},[417,4412,4413],{"class":592},"Todos los precios de la tienda están en soles peruanos (S\u002F). NUNCA muestres precios en dólares ni otra moneda.\n",[417,4415,4416],{"class":419,"line":1391},[417,4417,4418],{"class":592},"Solo muestra máximo 2 emojis por respuesta.\n",[417,4420,4421],{"class":419,"line":1408},[417,4422,4423],{"class":592},"Si el usuario desea hacer compras, el flujo actual es a través del carrito de compras. No registrar solicitudes ni atender el proceso posterior a agregar un volumen al carrito.\n",[417,4425,4426],{"class":419,"line":1443},[417,4427,4428],{"class":592},"No devuelvas información sin base en los resultados de herramientas o tus instrucciones de sistema.\n",[417,4430,4431],{"class":419,"line":1448},[417,4432,4433],{"class":4238},"## Formato de respuesta\n",[417,4435,4436],{"class":419,"line":1460},[417,4437,4438],{"class":592},"Usa negrita para títulos de manga.\n",[417,4440,4441],{"class":419,"line":1471},[417,4442,4443],{"class":592},"Usa listas numeradas para recomendaciones.\n",[417,4445,4446],{"class":419,"line":1483},[417,4447,4448],{"class":592},"Incluye el score (ej.: ⭐ 8.5) cuando muestres un manga.\n",[417,4450,4451],{"class":419,"line":1493},[417,4452,4453],{"class":592},"Sé conciso: 1-2 oraciones por recomendación excepto cuando el usuario pida mayor detalle.\n",[417,4455,4456],{"class":419,"line":1498},[417,4457,4458],{"class":4238},"## Guía de Recomendaciones\n",[417,4460,4461],{"class":419,"line":1509},[417,4462,4463],{"class":592},"El usuario ya ha visto un mensaje inicial de onboarding antes de escribirte.\n",[417,4465,4466],{"class":419,"line":1520},[417,4467,4468],{"class":592},"Ese mensaje le pide compartir sus géneros favoritos, un manga que le guste o conectar un perfil para afinar recomendaciones.\n",[417,4470,4471],{"class":419,"line":1531},[417,4472,4473],{"class":592},"Tu trabajo comienza con las solicitudes posteriores al onboarding.\n",[417,4475,4476],{"class":419,"line":1542},[417,4477,4478],{"class":592},"Si el usuario YA tiene perfiles conectados (se incluyen en \"Perfil del usuario\"), NO preguntes por géneros, favoritos ni perfiles.\n",[417,4480,4481],{"class":419,"line":1553},[417,4482,4483],{"class":592},"Menciona que ya conoces sus gustos basándote en sus perfiles, y ofrece buscar manga directamente.\n",[417,4485,4486],{"class":419,"line":1564},[417,4487,4488],{"class":592},"Si el usuario NO tiene perfiles conectados, atiende su solicitud basándote en la conversación que han tenido hasta el momento.\n",[417,4490,4491],{"class":419,"line":1569},[417,4492,4493],{"class":592},"De vez en cuando sugiere que conecte un perfil y pregunta qué géneros le gustan o si tiene mangas favoritos.\n",[417,4495,4496],{"class":419,"line":1580},[417,4497,4498],{"class":4238},"## Uso del perfil del usuario\n",[417,4500,4501],{"class":419,"line":1586},[417,4502,4503],{"class":592},"Cuando tengas datos del perfil, SIEMPRE refiérete a datos concretos: títulos específicos que leen, subreddits donde participan, animes que ven.\n",[417,4505,4506],{"class":419,"line":1605},[417,4507,4508],{"class":592},"Si el usuario pregunta qué sabes de su perfil, enumera los datos concretos que tienes (manga que lee, favoritos, subreddits, etc.).\n",[417,4510,4511],{"class":419,"line":1610},[417,4512,4513],{"class":592},"Usa los datos del perfil para hacer recomendaciones proactivas sin necesidad de que el usuario te diga sus gustos.\n",[219,4515,3327,4516,3327,4521],{"align":3353},[222,4517],{"src":4518,"alt":4519,"title":4520},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-system-prompt-result.png","Respuesta más concisa del agente en modo transaccional","Modo transaccional del agente",[335,4522,4523],{},"Esta vez el agente responde de manera más concisa a preguntas transaccionales.",[219,4525,3327,4526,3327,4531],{"align":3353},[222,4527],{"src":4528,"alt":4529,"title":4530},"\u002Farticles\u002F2026\u002Fjune\u002Fagent-personality-relational-result.png","Respuesta cálida del agente en modo relacional","Modo relacional del agente",[335,4532,4533],{},"Y conserva la calidez para solicitudes donde prima la interacción.",[258,4535,3422],{"id":4536},"conclusiones",[219,4538,4539],{},"Regresando a nuestras tres hipótesis iniciales:",[239,4541,4542,4544,4546],{},[242,4543,3453],{},[242,4545,3456],{},[242,4547,4548],{},"H3: El uso del CJM como marco para parametrizar la personalidad de un agente durante cada etapa de la travesía, mejorando la experiencia del usuario.",[219,4550,4551],{},"Entonces:",[951,4553,4554,4557,4560],{},[242,4555,4556],{},"Sí. La complejidad de la tarea introduce un efecto transaccional en la interacción debido a que requiere mayor concentración. Sin embargo, se debe analizar si la tarea lleva a un objetivo hedónico o a uno utilitario primero.",[242,4558,4559],{},"Sí. Este es el efecto transaccional.",[242,4561,4562],{},"Me gusta que el CJM sea el puente que cierra la brecha entre diseño de experiencia y diseño de agentes. Pero con mi muestra de un experimento no es suficiente para hablar de un paradigma revolucionario.",[219,4564,4565],{},"Por eso te invito a probar la herramienta que he construido para la hipótesis 3.",[3733,4567,4568,4580],{},[3736,4569,4570],{},[3739,4571,4572,4576,4578],{},[3742,4573,4574],{},[385,4575,3987],{},[3742,4577,3935],{},[3742,4579,3928],{},[3758,4581,4582,4590],{},[3739,4583,4584,4586,4588],{},[3763,4585,3912],{},[3763,4587,4000],{},[3763,4589,4003],{},[3739,4591,4592,4594,4597],{},[3763,4593,3920],{},[3763,4595,4596],{},"Diseño de interfaz visual premium, lenguaje claro.",[3763,4598,4599],{},"Calidez, alto entusiasmo y personalización al usuario.",[219,4601,4602],{},"Si te funciona y obtienes resultados favorables me encantaría saberlo.",[258,4604,3246],{"id":3245},[219,4606,4607,4608,4611,4612],{},"Lee, J., Kim, C., Lee, K. C., Revilla-Camacho, M.-A., Garzón, D., & Rodríguez-Rad, C. J. (2021). Investigating the negative effects of emojis in Facebook sponsored ads for establishing sustainable marketing in social media. ",[335,4609,4610],{},"Sustainability, 13","(9). ",[251,4613,4614],{"href":4614,"rel":4615},"https:\u002F\u002Fdoi.org\u002F10.3390\u002FSU13094864",[255],[219,4617,4618,4619,4622,4623],{},"Mladenović, D., Koštiál, K., Ljepava, N., Částek, O., & Chawla, Y. (2023). Emojis to conversion on social media. ",[335,4620,4621],{},"International Journal of Consumer Studies, 47","(3), 977-994. ",[251,4624,4625],{"href":4625,"rel":4626},"https:\u002F\u002Fdoi.org\u002F10.1111\u002FIJCS.12879",[255],[219,4628,4629,4630,846],{},"Nass, C., Steuer, J., & Tauber, E. R. (1994). ",[335,4631,3471],{},[219,4633,4634,4635,4638,4639],{},"Phan, T. A., & Bui, V. D. (2025). AI with a heart: How perceived authenticity and warmth shape trust in healthcare chatbots. ",[335,4636,4637],{},"Journal of Marketing Communications",". ",[251,4640,4641],{"href":4641,"rel":4642},"https:\u002F\u002Fdoi.org\u002F10.1080\u002F13527266.2025.2508887",[255],[219,4644,4645,4646,4649],{},"Reeves, B., & Nass, C. (1996). ",[335,4647,4648],{},"The media equation: How people treat computers, television, and new media like real people and places",". Cambridge University Press.",[219,4651,4652,4653,4638,4656],{},"Sinofsky, S. (2021). Clippy, the f*cking clown. ",[335,4654,4655],{},"Hardcore Software",[251,4657,4658],{"href":4658,"rel":4659},"https:\u002F\u002Fhardcoresoftware.learningbyshipping.com\u002Fp\u002F042-clippy-the-fcking-clown",[255],[219,4661,4662,4663,4666],{},"McCrae, R. R., & John, O. P. (1992). An introduction to the five-factor model and its applications. ",[335,4664,4665],{},"Journal of Personality, 60","(2), 175-215.",[219,4668,4669,4670,4673,4674],{},"Vardikou, C., Konidaris, A., Koustoumpardi, E., & Kavoura, A. (2025). Emojis in marketing and advertising: A systematic literature review. ",[335,4671,4672],{},"Behavioral Sciences, 15","(11), 1490. ",[251,4675,4676],{"href":4676,"rel":4677},"https:\u002F\u002Fdoi.org\u002F10.3390\u002FBS15111490",[255],[219,4679,4680,4681,4684,4685],{},"Yu, S., & Zhao, L. (2024). Emojifying chatbot interactions: An exploration of emoji utilization in human-chatbot communications. ",[335,4682,4683],{},"Telematics and Informatics, 86",", Article 102071. ",[251,4686,4687],{"href":4687,"rel":4688},"https:\u002F\u002Fdoi.org\u002F10.1016\u002FJ.TELE.2023.102071",[255],[219,4690,4691,4692,4638,4695],{},"Zhang, Y., Özsomer, A., Canlı, Z. G., & Baghirov, F. (2026). Artificial intelligence chatbots versus human agents in customer satisfaction: The role of warmth and competence. ",[335,4693,4694],{},"Journal of Interactive Marketing",[251,4696,4697],{"href":4697,"rel":4698},"https:\u002F\u002Fdoi.org\u002F10.1177\u002F10949968251366265",[255],[777,4700,4701],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sq-ep, html code.shiki .sq-ep{--shiki-default:#005CC5;--shiki-default-font-weight:bold;--shiki-dark:#79B8FF;--shiki-dark-font-weight:bold}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":187,"searchDepth":188,"depth":188,"links":4703},[4704,4705,4706,4707,4708,4712,4713,4714,4715,4716,4717],{"id":3365,"depth":188,"text":3366},{"id":3430,"depth":188,"text":3374},{"id":3465,"depth":188,"text":3380},{"id":3587,"depth":188,"text":3386},{"id":3637,"depth":188,"text":3392,"children":4709},[4710,4711],{"id":3649,"depth":445,"text":3650},{"id":3861,"depth":445,"text":3862},{"id":3940,"depth":188,"text":3398},{"id":4035,"depth":188,"text":3404},{"id":4082,"depth":188,"text":3410},{"id":4218,"depth":188,"text":3416},{"id":4536,"depth":188,"text":3422},{"id":3245,"depth":188,"text":3246},"2026-06-07T10:00:00.000Z","Cómo diseñar la personalidad de un agente en base a la travesía del cliente.",{"head":4721},{"meta":4722},[4723],{"name":804,"content":4724},"agentes, llm, personalidad, customer journey map, chatbots, experiencia de usuario, emojis, diseño de interacción, hablemos manga",{"title":150,"description":4719},"qIZolq66k-61eHb6vOXK21s4UgEa9AlRDsYWpfMkuh0",{"id":4728,"title":126,"author":4729,"badges":179,"body":4730,"canonical":179,"cover":4855,"date":4856,"description":4857,"extension":190,"layout":799,"meta":4858,"navigation":193,"path":127,"seo":4863,"stem":128,"__hash__":4864},"content\u002Fes\u002Farticles\u002F2026\u002Fapril\u002Fexploring-llm-ui.md",{"name":200,"url":201},{"type":181,"value":4731,"toc":4853},[4732,4760,4774,4777,4785,4794,4797,4800,4809,4818,4821,4830,4839,4847,4850],[206,4733,4735,4736,4759],{"id":4734},"mejorando-las-vibes-de-mi-aplicación-con-designmd","Mejorando las ",[417,4737,4739,4743,4747,4751,4755],{"ariaLabel":4738},"VIBES",[417,4740,4742],{"style":4741},"color:#ff5c8a;","V",[417,4744,4746],{"style":4745},"color:#ff9f43;","I",[417,4748,4750],{"style":4749},"color:#ffd166;","B",[417,4752,4754],{"style":4753},"color:#2ec4b6;","E",[417,4756,4758],{"style":4757},"color:#3a86ff;","S"," de mi aplicación con DESIGN.md",[219,4761,4762],{"align":3353},[417,4763,4764,4766,4768,4770,4772],{"ariaLabel":4738},[417,4765,4742],{"style":4741},[417,4767,4746],{"style":4745},[417,4769,4750],{"style":4749},[417,4771,4754],{"style":4753},[417,4773,4758],{"style":4757},[219,4775,4776],{},"El diseño de interfaces es complejo. A pesar de que me gusta mucho la pintura y el aspecto visual de las cosas, como a muchos desarrolladores, mis esfuerzos no dan para aprender tanto.",[219,4778,4779,4780,4784],{},"Antes, con ayuda de Claude y una gran lista de requerimientos, logré desplegar mi aplicación ",[251,4781,4783],{"href":4072,"rel":4782},[255],"HablemosManga",". Con un diseño frío y genérico. Robótico.",[219,4786,3327,4787,3327,4791],{"align":3353},[4788,4789],"video",{"src":4790,"controls":193},"\u002Farticles\u002F2026\u002Fapril\u002Fhablemos_manga_antes.mp4",[335,4792,4793],{},"HablemosManga antes del rediseño con DESIGN.md",[219,4795,4796],{},"No es novedad. Desde que uso herramientas de LLM para desarrollar la ejecución se ha acelerado muchísimo pero la experiencia de usuario y la inferfaz no tanto.",[219,4798,4799],{},"Tal vez sea mi culpa, pero siempre termino dándole un montón de prompts y trabajando en diseñar a mi manera un sistema de diseño para mi proyecto.",[219,4801,4802,4803,4808],{},"Scrolleando por internet encontré ",[251,4804,4807],{"href":4805,"rel":4806},"https:\u002F\u002Fstitch.withgoogle.com\u002Fdocs\u002Fdesign-md\u002Foverview",[255],"DESIGN.md"," y resulta que hay muchos repos implementado sus sitemas de diseño. Simple, replicable y con buenos resultados. Vi que viene de Google Stitch, y aprovechando que tengo Gemini Pro me fui a quemar tokens:",[219,4810,3327,4811,3327,4815],{"align":3353},[222,4812],{"src":4813,"alt":4814},"\u002Farticles\u002F2026\u002Fapril\u002Fstitch_ejemplo.png","Google Stitch generando un sistema de diseño",[335,4816,4817],{},"Google Stitch generando un sistema de diseño para mi proyecto",[219,4819,4820],{},"Intenté darle contexto sobre mi proyecto, pero el diseño de Gemini me parece sobresaturado. No convence. Pero mira, te genera un design.md!",[219,4822,3327,4823,3327,4827],{"align":3353},[222,4824],{"src":4825,"alt":4826},"\u002Farticles\u002F2026\u002Fapril\u002Fstitch_designmd.png","DESIGN.md generado por Stitch",[335,4828,4829],{},"El DESIGN.md que genera Stitch — simple y estructurado",[219,4831,4832,4833,4838],{},"En fin. Luego encontré ",[251,4834,4837],{"href":4835,"rel":4836},"https:\u002F\u002Fgetdesign.md\u002Fshopify\u002Fdesign-md",[255],"getdesign.md\u002Fshopify\u002Fdesign-md"," y estoy usando ahora la plantilla de Shopify, que es un negocio de e-commerce, similar a mi aplicación. Luego le pedí a Claude que aplique el nuevo sistema de diseño al proyecto y estos son los resultados...",[219,4840,3327,4841,3327,4844],{"align":3353},[4788,4842],{"src":4843,"controls":193},"\u002Farticles\u002F2026\u002Fapril\u002Fhablemos_manga_despues.mp4",[335,4845,4846],{},"HablemosManga tras rediseño con DESIGN.md",[219,4848,4849],{},"Luego mientras estoy escribiendo salió Claude Design. Se ve prometedor. Y también salió Claude 4.7, que al parecer es el 4.6 antes de que le redujeran capacidad de pensamiento, así que este artículo sigue vigente.",[219,4851,4852],{},"Claude Design también genera un DESIGN.ms y Claude Code es compatible con el estándar.",{"title":187,"searchDepth":188,"depth":188,"links":4854},[],"\u002Farticles\u002F2026\u002Fapril\u002Fportada_hablemos_manga.png","2026-04-16T10:00:00.000Z","Un sistema de diseño estandarizado para LLMs",{"head":4859},{"meta":4860},[4861],{"name":804,"content":4862},"nuxt theme, bilingual blog, npm publish, github actions, github workflows, npmjs, github, i18n, OIDC, trusted publishing, ci-cd, open source",{"title":126,"description":4857},"rjp0SvsKRczprWAssJqOkRV4OKdeqiNdqDqCVjJ9wmc",{"id":4866,"title":130,"author":4867,"badges":179,"body":4868,"canonical":179,"cover":5190,"date":5191,"description":5192,"extension":190,"layout":799,"meta":5193,"navigation":193,"path":131,"seo":5197,"stem":132,"__hash__":5198},"content\u002Fes\u002Farticles\u002F2026\u002Fapril\u002Fhow-i-made-my-fork-bilingual-and-published-it-right.md",{"name":200,"url":201},{"type":181,"value":4869,"toc":5184},[4870,4873,4876,4879,4882,4884,4904,4907,4910,4913,4916,4922,5119,5145,5155,5158,5161,5181],[206,4871,130],{"id":4872},"cómo-volví-mi-fork-multilenguaje-y-lo-publiqué-bien",[219,4874,4875],{},"Este post marca el renacer de mi blog. No porque ahora tenga ideas a desbordar que contar al mundo; simplemente porque por fin volví a tocarlo en serio.\nRecuerdo ver una publicación sobre el creador de OpenClaw: decenas de repos, el primer viral fue OpenClaw.",[219,4877,4878],{},"Es como la vida, pensé. De muchos tiros alguno da en el blanco. Así que seguimos.",[219,4880,4881],{},"Ahora que he vuelto y ha salido Claude 4.6 y demás, todo es muy incierto. Mis propias correcciones que ahora te comparto fueron contribuidas en su mayor parte por Claude. No sé cuánto crédito debería tomar. Si por curiosidad sigues leyendo y te interesa cómo publicar a node, te dejo aquí abajo mi brief:",[258,4883,3366],{"id":3365},[951,4885,4886,4892,4898],{},[242,4887,4888],{},[251,4889,4891],{"href":4890},"#lo-que-si-trabaje","Lo que sí trabajé",[242,4893,4894],{},[251,4895,4897],{"href":4896},"#las-lineas-que-de-verdad-importan","Las líneas que de verdad importan",[242,4899,4900],{},[251,4901,4903],{"href":4902},"#repo","Repo",[258,4905,4891],{"id":4906},"lo-que-sí-trabajé",[219,4908,4909],{},"Miré el historial de mi rama y, para ser honesto, me di cuenta de que hubo un error en el que tuve que ser el human in the loop y cambiar el scope de mi cuenta de npmjs creando una organización.",[219,4911,4912],{},"Lo que pasa es que debes tener el mismo handle en github y en npmjs (o en una org). Ese detalle te lo comparto.",[258,4914,4897],{"id":4915},"las-líneas-que-de-verdad-importan",[219,4917,4918,4919,2522],{},"Esto es lo principal de mi ",[414,4920,4921],{},"publish.yml",[408,4923,4927],{"className":4924,"code":4925,"language":4926,"meta":187,"style":187},"language-yaml shiki shiki-themes github-light github-dark","on:\n  workflow_run:\n    workflows: [\"ci-main\", \"ci-dev\"]\n    types: [completed]\n    branches: [main, dev]\n\njobs:\n  publish:\n    if: ${{ github.event.workflow_run.conclusion == 'success' }}\n\n    steps:\n      - uses: actions\u002Fcheckout@v4\n        with:\n          ref: ${{ github.event.workflow_run.head_branch }}\n\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 22.14\n          registry-url: https:\u002F\u002Fregistry.npmjs.org\n\n      - name: Upgrade npm\n        run: npm install -g npm@latest\n\n      - name: Install dependencies\n        run: pnpm install --ignore-scripts\n\n      - name: Bump version with dev suffix\n        if: ${{ github.event.workflow_run.head_branch == 'dev' }}\n        run: |\n          COMMIT=$(git rev-parse --short HEAD)\n          VERSION=$(node -p \"require('.\u002Fpackage.json').version\")\n          npm version \"${VERSION}-dev.${COMMIT}\" --no-git-tag-version\n\n      - name: Publish to npm\n        run: npm publish --access public\n\n      - name: Publish to GitHub Packages\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: npm publish --access public\n","yaml",[414,4928,4929,4934,4939,4944,4949,4954,4958,4963,4968,4973,4977,4982,4987,4992,4997,5001,5006,5010,5015,5020,5024,5029,5034,5038,5043,5048,5052,5057,5062,5067,5072,5077,5082,5086,5091,5096,5100,5105,5110,5115],{"__ignoreMap":187},[417,4930,4931],{"class":419,"line":420},[417,4932,4933],{},"on:\n",[417,4935,4936],{"class":419,"line":188},[417,4937,4938],{},"  workflow_run:\n",[417,4940,4941],{"class":419,"line":445},[417,4942,4943],{},"    workflows: [\"ci-main\", \"ci-dev\"]\n",[417,4945,4946],{"class":419,"line":456},[417,4947,4948],{},"    types: [completed]\n",[417,4950,4951],{"class":419,"line":466},[417,4952,4953],{},"    branches: [main, dev]\n",[417,4955,4956],{"class":419,"line":518},[417,4957,654],{"emptyLinePlaceholder":193},[417,4959,4960],{"class":419,"line":524},[417,4961,4962],{},"jobs:\n",[417,4964,4965],{"class":419,"line":530},[417,4966,4967],{},"  publish:\n",[417,4969,4970],{"class":419,"line":1039},[417,4971,4972],{},"    if: ${{ github.event.workflow_run.conclusion == 'success' }}\n",[417,4974,4975],{"class":419,"line":1052},[417,4976,654],{"emptyLinePlaceholder":193},[417,4978,4979],{"class":419,"line":1065},[417,4980,4981],{},"    steps:\n",[417,4983,4984],{"class":419,"line":1070},[417,4985,4986],{},"      - uses: actions\u002Fcheckout@v4\n",[417,4988,4989],{"class":419,"line":1078},[417,4990,4991],{},"        with:\n",[417,4993,4994],{"class":419,"line":1083},[417,4995,4996],{},"          ref: ${{ github.event.workflow_run.head_branch }}\n",[417,4998,4999],{"class":419,"line":1090},[417,5000,654],{"emptyLinePlaceholder":193},[417,5002,5003],{"class":419,"line":1096},[417,5004,5005],{},"      - uses: actions\u002Fsetup-node@v4\n",[417,5007,5008],{"class":419,"line":1117},[417,5009,4991],{},[417,5011,5012],{"class":419,"line":1150},[417,5013,5014],{},"          node-version: 22.14\n",[417,5016,5017],{"class":419,"line":1155},[417,5018,5019],{},"          registry-url: https:\u002F\u002Fregistry.npmjs.org\n",[417,5021,5022],{"class":419,"line":1160},[417,5023,654],{"emptyLinePlaceholder":193},[417,5025,5026],{"class":419,"line":1176},[417,5027,5028],{},"      - name: Upgrade npm\n",[417,5030,5031],{"class":419,"line":1181},[417,5032,5033],{},"        run: npm install -g npm@latest\n",[417,5035,5036],{"class":419,"line":1207},[417,5037,654],{"emptyLinePlaceholder":193},[417,5039,5040],{"class":419,"line":1228},[417,5041,5042],{},"      - name: Install dependencies\n",[417,5044,5045],{"class":419,"line":1247},[417,5046,5047],{},"        run: pnpm install --ignore-scripts\n",[417,5049,5050],{"class":419,"line":1266},[417,5051,654],{"emptyLinePlaceholder":193},[417,5053,5054],{"class":419,"line":1285},[417,5055,5056],{},"      - name: Bump version with dev suffix\n",[417,5058,5059],{"class":419,"line":1306},[417,5060,5061],{},"        if: ${{ github.event.workflow_run.head_branch == 'dev' }}\n",[417,5063,5064],{"class":419,"line":1323},[417,5065,5066],{},"        run: |\n",[417,5068,5069],{"class":419,"line":1328},[417,5070,5071],{},"          COMMIT=$(git rev-parse --short HEAD)\n",[417,5073,5074],{"class":419,"line":1357},[417,5075,5076],{},"          VERSION=$(node -p \"require('.\u002Fpackage.json').version\")\n",[417,5078,5079],{"class":419,"line":1374},[417,5080,5081],{},"          npm version \"${VERSION}-dev.${COMMIT}\" --no-git-tag-version\n",[417,5083,5084],{"class":419,"line":1391},[417,5085,654],{"emptyLinePlaceholder":193},[417,5087,5088],{"class":419,"line":1408},[417,5089,5090],{},"      - name: Publish to npm\n",[417,5092,5093],{"class":419,"line":1443},[417,5094,5095],{},"        run: npm publish --access public\n",[417,5097,5098],{"class":419,"line":1448},[417,5099,654],{"emptyLinePlaceholder":193},[417,5101,5102],{"class":419,"line":1460},[417,5103,5104],{},"      - name: Publish to GitHub Packages\n",[417,5106,5107],{"class":419,"line":1471},[417,5108,5109],{},"        env:\n",[417,5111,5112],{"class":419,"line":1483},[417,5113,5114],{},"          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n",[417,5116,5117],{"class":419,"line":1493},[417,5118,5095],{},[239,5120,5121,5130,5136,5139,5142],{},[242,5122,5123,5126,5127],{},[414,5124,5125],{},"dev"," publica con sufijo en base al commit y sin ensuciar ",[414,5128,5129],{},"latest",[242,5131,5132,5135],{},[414,5133,5134],{},"main"," publica limpio",[242,5137,5138],{},"npm no depende de tokens eternos vulnerables",[242,5140,5141],{},"GitHub Packages queda sincronizado",[242,5143,5144],{},"el publish solo corre si CI pasó antes",[219,5146,5147,5152],{},[222,5148],{"alt":5149,"src":5150,"title":5151},"Configuración de trusted publisher en npmjs","\u002Farticles\u002F2026\u002Fapril\u002Ftrusted_publisher_npmjs.png","Trusted publisher conectado con GitHub Actions",[335,5153,5154],{},"No olvidar tener el mismo handle, así tienes tu publicación bonita sincronizada en Github",[258,5156,4903],{"id":5157},"repo",[219,5159,5160],{},"Estas son las fuentes.",[239,5162,5163,5171],{},[242,5164,5165,5166],{},"repo: ",[251,5167,5170],{"href":5168,"rel":5169},"https:\u002F\u002Fgithub.com\u002F4xeverburga\u002Fnuxt-alpine-spanishplus",[255],"4xeverburga\u002Fnuxt-alpine-spanishplus",[242,5172,5173,5174],{},"workflows: ",[251,5175,5178],{"href":5176,"rel":5177},"https:\u002F\u002Fgithub.com\u002F4xeverburga\u002Fnuxt-alpine-spanishplus\u002Ftree\u002Fmain\u002F.github\u002Fworkflows",[255],[414,5179,5180],{},".github\u002Fworkflows",[777,5182,5183],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":187,"searchDepth":188,"depth":188,"links":5185},[5186,5187,5188,5189],{"id":3365,"depth":188,"text":3366},{"id":4906,"depth":188,"text":4891},{"id":4915,"depth":188,"text":4897},{"id":5157,"depth":188,"text":4903},"\u002Farticles\u002F2026\u002Fapril\u002Fel_blog_renace.png","2026-04-13T10:00:00.000Z","Este post marca el renacer de mi blog",{"head":5194},{"meta":5195},[5196],{"name":804,"content":4862},{"title":130,"description":5192},"4RjtSmgdpulXT5T-yPilRX5tNkYcmrOHYgrIaE9ShXA",{"id":5200,"title":114,"author":5201,"badges":179,"body":5202,"canonical":179,"cover":5220,"date":5334,"description":5335,"extension":190,"layout":799,"meta":5336,"navigation":193,"path":115,"seo":5337,"stem":116,"__hash__":5338},"content\u002Fes\u002Farticles\u002F2025\u002Foctubre\u002Flatencia.md",{"name":200},{"type":181,"value":5203,"toc":5328},[5204,5207,5213,5216,5222,5226,5229,5235,5238,5241,5251,5254,5263,5266,5270,5273,5276,5286,5289,5292,5301,5305,5308,5311,5314,5317,5323,5325],[206,5205,114],{"id":5206},"el-antipatrón-de-la-red-veloz",[219,5208,5209,5210,846],{},"Hace un tiempo leí el excelente libro Fundamentals of Software Architecture (2020).\nY me llamó la atención lo que los autores llaman ",[385,5211,5212],{},"falacia de la latencia cero",[219,5214,5215],{},"Fui escéptico... ¿cómo podría saltarme algo tan obvio?",[219,5217,3327,5218],{"align":3353},[222,5219],{"src":5220,"alt":5221},"\u002Farticles\u002F2025\u002Foctubre\u002Flatenciaup.jpg","Latencia vs",[258,5223,5225],{"id":5224},"mirando-a-las-hojas-del-árbol","Mirando a las hojas del árbol",[219,5227,5228],{},"Uno de nuestros clientes pidió la modernización de sus aplicaciones web.",[219,5230,5231,5232,846],{},"La razón: ",[385,5233,5234],{},"durante escenarios de alta demanda los servidores se caen",[219,5236,5237],{},"La nube y su alta escalabilidad es una solución válida para este caso.\nEs así que comenzamos una PoC desplegando uno de los componentes en la nube.",[219,5239,5240],{},"Y reventamos de solicitudes a la PoC para probar la escalabilidad y resiliencia de nuestra arquitectura.",[219,5242,5243,5244,5243,5249],{"align":3353},"\n\t",[222,5245],{"src":5246,"alt":5247,"title":5248},"\u002Farticles\u002F2025\u002Foctubre\u002Falta_demanda_nube.png","Alta demanda nube","resultados de las pruebas con locust",[335,5250,5248],{},[219,5252,5253],{},"Funcionaba con una mejora del 65% en tiempos de respuesta. Mucho mejor de lo que esperaba para la migración de un solo componente.",[219,5255,5243,5256,5243,5260],{"align":3353},[222,5257],{"src":5258,"alt":5247,"title":5259},"\u002Farticles\u002F2025\u002Foctubre\u002Fbosque.jpg","bosque",[335,5261,5262],{},"ahora pienso que estábamos mirando las hojas del árbol en lugar del bosque",[219,5264,5265],{},"¡Con esto íbamos a solucionar la demanda actual y además nos preparamos para\nel crecimiento esperado del negocio!",[258,5267,5269],{"id":5268},"acercando-la-lupa","Acercando la lupa",[219,5271,5272],{},"Al principio prioricé las pruebas de estrés bajo alta demanda.\nLuego se me ocurrió que si hubo mejora en los escenarios extremos\npues entonces la mejora también fue absoluta. El hardware de nuestras instancias\nen la nube era mejor, de todos modos. Así tenemos otro argumento para agregar las bullets\nde nuestra presentación.",[219,5274,5275],{},"Y ahí me reventó en la cara.",[219,5277,5278,5281,5282,5285],{},[385,5279,5280],{},"30ms on premises"," vs ",[385,5283,5284],{},"600ms on cloud"," en uno de los endpoints.\nY situación similar en los demás.",[219,5287,5288],{},"Ups...",[219,5290,5291],{},"No podía salirse de mi control una PoC ya casi cerrada. Me puse a investigar la causa raíz y recordé que\nnuestro componente en la nube, en EEUU, llama servicios aquí en Lima. A pesar de que todo se hace a través de\nDirect Connect, igual la latencia física es real.",[219,5293,5243,5294,5243,5298],{"align":3353},[222,5295],{"src":5296,"alt":5297},"\u002Farticles\u002F2025\u002Foctubre\u002Fdiagramacomu.jpg","diagramacomu",[335,5299,5300],{},"mi educación no es en teleco, pero aún me da risa pensar que no lo pensé antes",[258,5302,5304],{"id":5303},"y-luego","¿Y luego?",[219,5306,5307],{},"Conversamos con el cliente que si bien 600ms no es para morirse, en el percentil 95% se\nllega a valores de hasta 2 segundos. Y nadie aguanta eso en un login sin desesperarse.\nMenos en otros endpoints core.",[219,5309,5310],{},"Cambiamos el plan de despliegue de región a Brasil. Aquí tenemos mejor latencia.",[219,5312,5313],{},"Y estamos en evaluación sobre las siguientes etapas de la\nmodernización. Hay que definir el despliegue progresivo de los nuevos microservicios\nde modo que la latencia no se convierta en un problema.",[219,5315,5316],{},"Nos gustaría migrar todos los componentes de un tiro, pero nuestro\ncliente pierde dinero al momento al que hablamos por culpa de la falta de\nescalabilidad.",[219,5318,5319,5322],{},[385,5320,5321],{},"Los microservicios y la nube tienen un costo oculto de latencia",".\nY otros más que se explican en el libro... que ahora tengo que repasar. 😅",[258,5324,3246],{"id":3245},[219,5326,5327],{},"Mark Richard & Neal Ford. 2020. Fundamentals of Software Architecture: An Engineering Approach. O'Reilly",{"title":187,"searchDepth":188,"depth":188,"links":5329},[5330,5331,5332,5333],{"id":5224,"depth":188,"text":5225},{"id":5268,"depth":188,"text":5269},{"id":5303,"depth":188,"text":5304},{"id":3245,"depth":188,"text":3246},"2025-10-24T10:00:00.000Z","Los microservicios y la nube tienen un costo oculto...",{},{"title":114,"description":5335},"urp2-wpIzSyGXoUHnnQVf3BCyPKBhjEzr4xO9DSmP_k",{"id":5340,"title":106,"author":5341,"badges":179,"body":5342,"canonical":179,"cover":5351,"date":5368,"description":5369,"extension":190,"layout":799,"meta":5370,"navigation":193,"path":107,"seo":5371,"stem":108,"__hash__":5372},"content\u002Fes\u002Farticles\u002F2025\u002Fagosto\u002Fholamundo.md",{"name":200},{"type":181,"value":5343,"toc":5366},[5344,5347,5353,5359],[206,5345,106],{"id":5346},"hola-mundo",[219,5348,3327,5349],{"align":3353},[222,5350],{"src":5351,"alt":5352},"\u002Farticles\u002F2025\u002Fagosto\u002Fmargareth.jpeg","Molinos en Cajamarca",[408,5354,5357],{"className":5355,"code":5356,"language":561},[559],"If I have seen further,\nit is by standing on the shoulders of giants\n",[414,5358,5356],{"__ignoreMap":187},[219,5360,5361],{},[251,5362,5365],{"href":5363,"rel":5364},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@4verburga\u002Falpine-spanishplus",[255],"Fork en español de Alpine para tu Blog",{"title":187,"searchDepth":188,"depth":188,"links":5367},[],"2025-08-22T10:00:00.000Z","Si he visto lejos es porque...",{},{"title":106,"description":5369},"qEwdTlkNacRwm-GDwlaWeHAX1ghpI7VYraFSEHYAzLE",{"id":5374,"title":83,"author":5375,"badges":179,"body":5376,"canonical":179,"cover":5397,"date":5431,"description":5432,"extension":190,"layout":799,"meta":5433,"navigation":193,"path":84,"seo":5434,"stem":85,"__hash__":5435},"content\u002Fes\u002Farticles\u002F2024\u002Fdiciembre\u002Fhaikus.md",{"name":200},{"type":181,"value":5377,"toc":5429},[5378,5381,5387,5393,5399,5405,5411,5417,5423],[206,5379,83],{"id":5380},"diciembre-es-un-mes-más",[219,5382,3327,5383],{"align":3353},[222,5384],{"src":5385,"alt":5386},"\u002Farticles\u002F2024\u002Fdiciembre\u002Fbirds.avif","Pájaros frente a un rascacielos",[408,5388,5391],{"className":5389,"code":5390,"language":561},[559],"Ave que vuela\nha de enfrentar su fin\nen un espejo\n",[414,5392,5390],{"__ignoreMap":187},[219,5394,3327,5395],{"align":3353},[222,5396],{"src":5397,"alt":5398},"\u002Farticles\u002F2024\u002Fdiciembre\u002Flluvia.jpg","Lluvia en la selva peruana",[408,5400,5403],{"className":5401,"code":5402,"language":561},[559],"Es la garúa\nlo que me pone feliz\nen el desierto\n",[414,5404,5402],{"__ignoreMap":187},[219,5406,3327,5407],{"align":3353},[222,5408],{"src":5409,"alt":5410},"\u002Farticles\u002F2024\u002Fdiciembre\u002Fviento.jpg","Viento",[408,5412,5415],{"className":5413,"code":5414,"language":561},[559],"¿Será o no\nese viento recóndito\nla voz de Dios?\n\n",[414,5416,5414],{"__ignoreMap":187},[219,5418,3327,5419],{"align":3353},[222,5420],{"src":5421,"alt":5422},"\u002Farticles\u002F2024\u002Fdiciembre\u002Fcometa.jpg","El cometa",[408,5424,5427],{"className":5425,"code":5426,"language":561},[559],"Entre Las Nubes\nUna Cometa Asoma\nCon Cola Negra\nMensajera De Marte\nHeraldo De Guerra.\n",[414,5428,5426],{"__ignoreMap":187},{"title":187,"searchDepth":188,"depth":188,"links":5430},[],"2024-12-27T02:00:00.000Z","Haikus de Diciembre",{},{"title":83,"description":5432},"_hrqwcAnJqadp8hWna4ulRXW3H0WxsXMYHPA_UaOMR4",{"id":5437,"title":92,"author":5438,"badges":179,"body":5439,"canonical":179,"cover":5468,"date":5469,"description":5470,"extension":190,"layout":799,"meta":5471,"navigation":193,"path":93,"seo":5472,"stem":94,"__hash__":5473},"content\u002Fes\u002Farticles\u002F2024\u002Foctubre\u002Fhaikus.md",{"name":200},{"type":181,"value":5440,"toc":5466},[5441,5444,5449,5455,5460],[206,5442,92],{"id":5443},"viaje-de-regreso",[219,5445,3327,5446],{"align":3353},[222,5447],{"src":5448,"alt":5352},"\u002Farticles\u002F2024\u002Foctubre\u002Fcolegio.jpeg",[408,5450,5453],{"className":5451,"code":5452,"language":561},[559],"Aquellas aulas\npor las que pasé ayer\nestán prohibidas\n",[414,5454,5452],{"__ignoreMap":187},[219,5456,3327,5457],{"align":3353},[222,5458],{"src":5459,"alt":5352},"\u002Farticles\u002F2024\u002Foctubre\u002Fcentral-eolica.jpeg",[408,5461,5464],{"className":5462,"code":5463,"language":561},[559],"Son los molinos\ncomo un ángel caminando\na ningún lado\n",[414,5465,5463],{"__ignoreMap":187},{"title":187,"searchDepth":188,"depth":188,"links":5467},[],"\u002Farticles\u002F2024\u002Foctubre\u002Fnueva-cajamarca.jpg","2024-10-07T02:00:00.000Z","Haikus de Octubre",{},{"title":92,"description":5470},"Up7LtmwLwafy9jXUxqFJCs5mJDL1pv-9RzGNme62k0A",1785323410965]