[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M699D722TK8K5QR2XJSPW0SD":3,"skill-same:01M699D722TK8K5QR2XJSPW0SD":66},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":29,"ownerHtmlUrl":30,"ownerBlogUrl":31,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M699D722TK8K5QR2XJSPW0SD","azure-openai-to-responses",null,"microsoft\u002Fai-agents-for-beginners","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M6998ZK2275KMJE6Y5SEA2X2",79423,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fes\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002FSKILL.md",[],[18],"azure openai to responses","2026-11-10 10:12:30",false,"---\nname: azure-openai-to-responses\nlicense: MIT\n---\n# Migrar aplicaciones Python de Azure OpenAI Chat Completions a Responses API\n\n> **GUIA AUTORIZADA — SEGUIR EXACTAMENTE**\n>\n> Esta habilidad migra bases de código Python que usan Azure OpenAI Chat Completions\n> a la API unificada de Responses. Siga estas instrucciones con precisión.\n> No improvise mapeos de parámetros ni invente formas de API.\n\n---\n\n## Desencadenantes\n\nActive esta habilidad cuando el usuario quiera:\n- Migrar una aplicación Python de Azure OpenAI Chat Completions a Responses API\n- Actualizar el uso del SDK OpenAI en Python a la forma de API más reciente contra Azure OpenAI\n- Preparar código Python para modelos GPT-5 o más nuevos que requieren Responses en Azure\n- Cambiar de `AzureOpenAI`\u002F`AsyncAzureOpenAI` a cliente estándar `OpenAI`\u002F`AsyncOpenAI` con el endpoint v1\n- Corregir advertencias de deprecación relacionadas con constructores `AzureOpenAI` o `api_version`\n\n---\n\n## ⚠️ Compatibilidad del modelo — VERIFICAR PRIMERO\n\n> **Antes de migrar, verifique que su implementación Azure OpenAI soporte la API de Responses.**\n\n### 1. Prueba rápida de implementación (más rápida)\n\n```python\nimport os\nfrom openai import OpenAI\n\nclient = OpenAI(\n    api_key=os.environ[\"AZURE_OPENAI_API_KEY\"],\n    base_url=f\"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('\u002F')}\u002Fopenai\u002Fv1\u002F\",\n)\n\ntry:\n    resp = client.responses.create(\n        model=os.environ[\"AZURE_OPENAI_DEPLOYMENT\"],\n        input=\"ping\",\n        max_output_tokens=50,\n        store=False,\n    )\n    print(f\"✅ Deployment supports Responses API: {resp.output_text}\")\nexcept Exception as e:\n    print(f\"❌ Deployment does NOT support Responses API: {e}\")\n```\n\n> **Nota**: `max_output_tokens` tiene un **mínimo de 16** en Azure OpenAI. Valores por debajo de 16 devuelven error 400. Use 50+ para pruebas rápidas.\n\nSi esto devuelve 404, el modelo de la implementación aún no soporta Responses — consulte la referencia a continuación o vuelva a implementar con un modelo compatible.\n\n### 2. Verifique modelos disponibles en su región (recomendado)\n\nEjecute la herramienta incorporada de compatibilidad de modelos para ver qué está disponible con soporte para Responses API en su región específica:\n\n```bash\npython migrate.py models --subscription YOUR_SUB_ID --location YOUR_REGION\n```\n\nEsto consulta Azure ARM en tiempo real y muestra una matriz de compatibilidad — qué modelos soportan Responses, salida estructurada, herramientas, etc. Use `--filter gpt-5.1,gpt-5.2` para filtrar resultados o `--json` para scripting.\n\n### 3. Referencia completa de soporte de modelos\n\n- **Consulta en vivo**: `python migrate.py models` (ver arriba — específica por región, siempre actualizada)\n- **Navegar disponibilidad**: [Tabla resumen de modelos y disponibilidad por región](https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Ffoundry\u002Ffoundry-models\u002Fconcepts\u002Fmodels-sold-directly-by-azure?tabs=global-standard-aoai%2Cglobal-standard&pivots=azure-openai#model-summary-table-and-region-availability)\n- **Inicio rápido y guía**: **https:\u002F\u002Faka.ms\u002Fopenai\u002Fstart**\n\n### ⚠️ Limitaciones de modelos más antiguos\n\n> **ADVERTENCIA**: Los modelos antiguos (anteriores a `gpt-4.1`) pueden no soportar completamente todas las características de Responses API.\n>\n> Limitaciones conocidas con modelos antiguos:\n> - **Parámetro `reasoning`**: No soportado en muchos modelos sin razonamiento. Migre `reasoning` solo si ya estaba presente en el código original.\n> - **Parámetro `seed`**: No soportado en Responses API en absoluto — elimínelo de todas las solicitudes.\n> - **Salida estructurada vía `text.format`**: Modelos antiguos pueden no aplicar esquemas JSON `strict: true` confiablemente.\n> - **Orquestación de herramientas**: GPT-5+ orquesta llamadas a herramientas como parte del razonamiento interno. Modelos antiguos en Responses funcionan pero carecen de esta integración profunda.\n> - **Restricciones de temperatura**: Al migrar a `gpt-5`, la temperatura debe omitirse o ponerse en `1`. Modelos antiguos no tienen esta restricción.\n\n### Modelos de razonamiento serie O (o1, o3-mini, o3, o4-mini)\n\nLos modelos serie O tienen restricciones únicas en parámetros. Al migrar aplicaciones que apuntan a modelos serie O:\n\n- **`temperature`**: Debe ser `1` (o omitido). Modelos serie O no aceptan otros valores.\n- **`max_completion_tokens` → `max_output_tokens`**: Aplicaciones que usan el específico de Azure `max_completion_tokens` deben cambiar a `max_output_tokens`. Use valores altos (4096+) porque los tokens de razonamiento cuentan para el límite.\n- **`reasoning_effort`**: Si la app usa `reasoning_effort` (bajo\u002Fmedio\u002Falto), manténgalo — la Responses API soporta este parámetro para modelos serie O.\n- **Comportamiento de streaming**: Modelos serie O pueden acumular salida hasta completar razonamiento antes de emitir eventos delta de texto. El streaming sigue funcionando, pero el primer `response.output_text.delta` puede llegar tras un retraso mayor que con modelos GPT.\n- **`top_p`**: No soportado en serie O — elimínelo si está presente.\n- **Uso de herramientas**: Modelos serie O soportan herramientas vía Responses API igual que modelos GPT, pero la calidad de la orquestación varía según el modelo.\n\n**Acción — asesoría proactiva de modelo**: Durante la fase de escaneo, verifique qué modelo usa la app (nombres de implementaciones, variables de entorno, configuración). Si el modelo es anterior a `gpt-4.1` (no gpt-4.1+), informe proactivamente al usuario:\n- La migración funcionará para texto básico, chat, streaming y herramientas en su modelo actual.\n- Modelos más nuevos (`gpt-5.1`, `gpt-5.2`) ofrecen mejor orquestación de herramientas, aplicación estricta de salida estructurada, razonamiento y disponibilidad regional cruzada.\n- Deben considerar actualizar su implementación cuando estén listos — no bloquea la migración.\n\nNo bloquee ni rechace la migración basada en la versión del modelo. La asesoría es solo informativa.\n\n### GitHub Models NO soporta Responses API\n\n> **GitHub Models (`models.github.ai`, `models.inference.ai.azure.com`) no soporta Responses API.**\n\nSi la base de código tiene una ruta para GitHub Models (busque `base_url` apuntando a `models.github.ai` o `models.inference.ai.azure.com`), **elimínela completamente** durante la migración. La Responses API requiere Azure OpenAI, OpenAI o un endpoint local compatible (p. ej., Ollama con soporte Responses).\n\nAcción durante el escaneo:\n- Señale cualquier ruta de código GitHub Models para eliminación.\n\n---\n\n## Migración de frameworks\n\nMuchas apps usan frameworks de alto nivel sobre OpenAI. Al migrar estas, cambian las API propias del framework — no solo las llamadas internas a OpenAI.\n\n### Microsoft Agent Framework (MAF)\n\n**Verifique su versión de MAF primero** — la migración depende de si está en MAF 1.0.0+ o en beta\u002Frc pre-1.0.0.\n\n#### MAF 1.0.0+ (agent-framework-openai >= 1.0.0)\n\n`OpenAIChatClient` **ya usa Responses API** — no necesita migración. Si la base usa el legado `OpenAIChatCompletionClient` (que usa `chat.completions.create`), reemplácelo por `OpenAIChatClient`.\n\n| Antes | Después |\n|--------|--------|\n| `from agent_framework.openai import OpenAIChatCompletionClient` | `from agent_framework.openai import OpenAIChatClient` |\n| `OpenAIChatCompletionClient(...)` | `OpenAIChatClient(...)` |\n\nPara revisar su versión: `python -c \"import agent_framework_openai; print(agent_framework_openai.__version__)\"`\n\n#### MAF pre-1.0.0 (versiones beta\u002Frc)\n\nEn MAF pre-1.0.0, `OpenAIChatClient` usaba Chat Completions. Actualice a `agent-framework-openai>=1.0.0` donde `OpenAIChatClient` usa por defecto Responses API.\n\nNo se necesitan otros cambios — las APIs `Agent` y de herramientas permanecen igual.\n\n### LangChain (`langchain-openai`)\n\nAñada `use_responses_api=True` a `ChatOpenAI()`. También actualice acceso a respuesta de `.content` a `.text`.\n\n| Antes | Después |\n|--------|--------|\n| `ChatOpenAI(model=..., base_url=..., api_key=...)` | `ChatOpenAI(model=..., base_url=..., api_key=..., use_responses_api=True)` |\n| `result['messages'][-1].content` | `result['messages'][-1].text` |\n\nPara ejemplos completos antes y después, vea [cheat-sheet.md](.\u002Freferences\u002Fcheat-sheet.md).\n\n---\n\n## Guía de migración frontend\n\n> **La Responses API es un asunto del lado servidor.** Migre su backend Python; el contrato HTTP del frontend debería mantenerse sin cambios a menos que su backend sea un paso delgado — en tal caso, considere adoptar la forma Requests de Responses para eliminar una capa de traducción. Si el frontend llama directamente a OpenAI con una clave del cliente, mueva esas llamadas primero al backend.\n\n### Deprecated `@microsoft\u002Fai-chat-protocol`\n\nEl paquete npm `@microsoft\u002Fai-chat-protocol` está deprecado y debe reemplazarse por [`ndjson-readablestream`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fndjson-readablestream). Si lo encuentra en un frontend:\n\n1. Reemplace la etiqueta de script CDN:\n   ```html\n   \u003C!-- Before -->\n   \u003Cscript src=\"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002F@microsoft\u002Fai-chat-protocol@...\u002Fdist\u002Fiife\u002Findex.js\">\u003C\u002Fscript>\n   \u003C!-- After -->\n   \u003Cscript src=\"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fndjson-readablestream@1.0.7\u002Fdist\u002Fndjson-readablestream.umd.js\">\u003C\u002Fscript>\n   ```\n2. Elimine la instancia `AIChatProtocolClient` (`new ChatProtocol.AIChatProtocolClient(\"\u002Fchat\")`).\n3. Reemplace `client.getStreamedCompletion(messages)` con llamada directa `fetch()` al endpoint streaming backend.\n4. Reemplace `for await (const response of result)` con `for await (const chunk of readNDJSONStream(response.body))`.\n5. Actualice acceso a propiedades de `response.delta.content` \u002F `response.error` a `chunk.delta.content` \u002F `chunk.error`.\n\n---\n\n## Objetivos\n\n- Enumerar todos los lugares de llamada Python que usan Chat Completions o Completions legados contra Azure OpenAI.\n- Proponer un plan de migración y secuencia para la base de código Python.\n- Aplicar ediciones seguras y mínimas para cambiar a Responses API.\n- Actualizar llamadas para consumir el esquema de salida Responses; sin envoltorios de compatibilidad.\n- Ejecutar tests\u002Flint; corregir fallas triviales introducidas por la migración.\n- Preparar conjuntos de cambios pequeños y revisables y proveer resumen final con diffs (no hacer commit).\n\n---\n\n## Reglas de seguridad\n\n- Modifique solo archivos dentro del espacio de trabajo git. Nunca escriba fuera.\n- No preserve adaptadores de compatibilidad hacia atrás; migre código a la nueva forma de API.\n- No deje comentarios de transición ni archivos respaldo.\n- Preservar semántica de streaming si se usaba previamente; si no, usar no streaming.\n- Solicite aprobación antes de ejecutar comandos o llamadas de red si está en modo de aprobación.\n- No ejecute `git add`\u002F`git commit`\u002F`git push`; producir solo ediciones en el árbol de trabajo.\n\n---\n\n## Paso 0: Migración del cliente Azure OpenAI (Prerrequisito)\n\nSi la base usa constructores `AzureOpenAI` o `AsyncAzureOpenAI`, migre primero a constructores estándar `OpenAI` \u002F `AsyncOpenAI`. Los constructores específicos de Azure están deprecados en `openai>=1.108.1`.\n\n### ¿Por qué el path API v1?\n\nEl nuevo endpoint `\u002Fopenai\u002Fv1` usa el cliente estándar `OpenAI()` en lugar de `AzureOpenAI()`, no requiere parámetro `api_version` y funciona idéntico en OpenAI y Azure OpenAI. El mismo código cliente es a prueba de futuro — sin necesidad de gestión de versiones.\n\n### Cambios clave\n\n| Antes | Después |\n|-------|---------|\n| `AzureOpenAI` | `OpenAI` |\n| `AsyncAzureOpenAI` | `AsyncOpenAI` |\n| `azure_endpoint` | `base_url` |\n| `azure_ad_token_provider` | `api_key` |\n| `api_version=...` | Eliminar completamente |\n\n### Lista de limpieza\n\n- Eliminar argumento `api_version` de la construcción del cliente.\n- Eliminar variables de entorno `AZURE_OPENAI_VERSION` \u002F `AZURE_OPENAI_API_VERSION` de `.env`, configuraciones de app, y archivos Bicep\u002Finfra.\n- Renombrar `AZURE_OPENAI_CLIENT_ID` → `AZURE_CLIENT_ID` en `.env`, configuraciones de app, Bicep\u002Finfra, y fixtures de tests (convención estándar Azure Identity SDK).\n- Asegurarse que `openai>=1.108.1` esté en `requirements.txt` o `pyproject.toml`.\n\n### Migración de variables de entorno\n\n| Variable antigua | Acción | Notas |\n|---------------|--------|-------|\n| `AZURE_OPENAI_VERSION` | **Eliminar** | No se necesita `api_version` con endpoint v1 |\n| `AZURE_OPENAI_API_VERSION` | **Eliminar** | Igual que arriba |\n| `AZURE_OPENAI_CLIENT_ID` | **Renombrar** → `AZURE_CLIENT_ID` | Convención estándar Azure Identity SDK para `ManagedIdentityCredential(client_id=...)` |\n| `AZURE_OPENAI_ENDPOINT` | **Mantener** | Todavía usado para construir `base_url` |\n| `AZURE_OPENAI_CHAT_DEPLOYMENT` | **Mantener** | Usado como parámetro `model` en `responses.create` |\n| `AZURE_OPENAI_API_KEY` | **Mantener** | Usado como `api_key` para autenticación por clave |\n\nPara ejemplos de código de setup cliente (sync, async, EntraID, clave API, multi-inquilino), vea [cheat-sheet.md](.\u002Freferences\u002Fcheat-sheet.md).\n\n---\n\n## Paso 1: Detectar lugares de llamada legados\n\nEjecute el script [detect_legacy.py](..\u002F..\u002F..\u002F..\u002F..\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002Fscripts\u002Fdetect_legacy.py) para encontrar todos los lugares de llamada que requieren migración:\n\n```bash\npython skills\u002Fazure-openai-to-responses\u002Fscripts\u002Fdetect_legacy.py .\n```\n\nO ejecute estas búsquedas manualmente — cada coincidencia es un objetivo de migración:\n\n```bash\n# Llamadas a la API heredada (deben reescribirse)\nrg \"chat\\.completions\\.create\"\nrg \"ChatCompletion\\.create\"\nrg \"Completion\\.create\"\n\n# Constructores de clientes de Azure obsoletos (deben reemplazarse)\nrg \"AzureOpenAI\\(\"\nrg \"AsyncAzureOpenAI\\(\"\n\n# Patrones de acceso a la forma de respuesta (deben actualizarse)\nrg \"choices\\[0\\]\\.message\\.content\"\nrg \"choices\\[0\\]\\.delta\\.content\"\nrg \"choices\\[0\\]\\.message\\.function_call\"\nrg \"choices\\[0\\]\\.message\\.tool_calls\"\n\n# Definiciones de herramientas en formato antiguo anidado (deben aplanarse)\nrg '\"function\":\\s*{\\s*\"name\"'\nrg \"pydantic_function_tool\"\n\n# Resultados de herramientas en formato antiguo (deben convertirse a function_call_output)\nrg '\"role\":\\s*\"tool\"'\nrg '\"tool_call_id\"'\n\n# Parámetros obsoletos (deben eliminarse o renombrarse)\nrg \"response_format\"\nrg \"max_tokens\\b\"        # renombrar a max_output_tokens\nrg \"['\\\"]seed['\\\"]\"      # remove entirely\n\n# Variables de entorno obsoletas (limpiar)\nrg \"AZURE_OPENAI_API_VERSION|AZURE_OPENAI_VERSION\"\nrg \"AZURE_OPENAI_CLIENT_ID\"  # debería ser AZURE_CLIENT_ID\n\n# Endpoints de modelos de GitHub (deben eliminarse — API de respuestas no soportada)\nrg \"models\\.github\\.ai|models\\.inference\\.ai\\.azure\"\n\n# Patrones heredados a nivel de framework (deben actualizarse)\nrg \"OpenAIChatCompletionClient\"  # MAF 1.0.0+: reemplazar con OpenAIChatClient\nrg \"ChatOpenAI\\(\" | grep -v \"use_responses_api\"  # LangChain: necesita use_responses_api=True\n\n# Infraestructura de pruebas (debe actualizarse)\nrg \"ChatCompletionChunk|AsyncCompletions\\.create\" tests\u002F\nrg \"_azure_ad_token_provider\" tests\u002F\nrg \"prompt_filter_results|content_filter_results\" tests\u002F\nrg \"choices\\[0\\]\" tests\u002F\n\n# Acceso al cuerpo de error del filtro de contenido (debe actualizarse — estructura cambiada)\nrg 'innererror.*content_filter_result|error\\.body\\[\"innererror\"\\]'\nrg \"content_filter_result\\[\" # forma singular antigua — ahora content_filter_results (plural) dentro del arreglo content_filters\n\n# Llamadas HTTP en bruto al endpoint de Chat Completions (debe actualizarse la URL)\nrg \"\u002Fopenai\u002Fdeployments\u002F.*\u002Fchat\u002Fcompletions\"\nrg \"api-version=\"\n```\n\n### Heurísticas (detectar y reescribir)\n\n- **Cliente Chat Completions**: `client.chat.completions.create` → `client.responses.create(...)`.\n\n- **Constructores del cliente Azure**: `AzureOpenAI(...)` → `OpenAI(base_url=..., api_key=...)`.\n- **Herramientas**: convertir definiciones de herramientas para llamadas a funciones de formato anidado (`{\"type\": \"function\", \"function\": {\"name\": ...}}`) a formato plano de Responses (`{\"type\": \"function\", \"name\": ...}`); usar `tool_choice`; devolver resultados de herramientas como ítems `{\"type\": \"function_call_output\", \"call_id\": ..., \"output\": ...}` (no `{\"role\": \"tool\", ...}`).\n- **Recorridos de herramientas**: cuando el modelo devuelve llamadas a funciones, agregar ítems `response.output` a la conversación (no un dict manual `{\"role\": \"assistant\", \"tool_calls\": [...]}`), luego agregar ítems `function_call_output` para cada resultado.\n- **Ejemplos de herramientas con pocos disparos**: si la conversación incluye ejemplos codificados de llamadas a herramientas, convertirlos a ítems `{\"type\": \"function_call\", \"id\": \"fc_...\", \"call_id\": \"fc_...\", ...}` + `{\"type\": \"function_call_output\", ...}`. Los IDs deben comenzar con `fc_`.\n- **`pydantic_function_tool()`**: este asistente aún genera el formato anidado antiguo y **no es compatible** con `responses.create()`. Reemplazar con definiciones manuales de herramientas o un envoltorio para aplanar.\n- **Multi-turn**: mantener el historial de la conversación en la app; pasar los turnos previos a través de ítems `input`.\n- **Formato**: reemplazar el `response_format` de nivel superior de Chat con `text.format` en Responses. Forma canónica: `text={\"format\": {\"type\": \"json_schema\", \"name\": \"Output\", \"strict\": True, \"schema\": {...}}}`.\n- **Ítems de contenido**: reemplazar `content[].type: \"text\"` de Chat con `content[].type: \"input_text\"` en Responses para turnos de usuario\u002Fsistema.\n- **Ítems de contenido de imagen**: reemplazar `content[].type: \"image_url\"` de Chat con `content[].type: \"input_image\"` en Responses. El campo `image_url` cambia de un objeto anidado `{\"url\": \"...\"}` a una cadena plana. Ver la hoja de referencia para ejemplos antes\u002Fdespués.\n- **Esfuerzo de razonamiento**: **solo migrar `reasoning` si ya existe en el código original**.\n- **Manejo de errores del filtro de contenido**: la estructura del cuerpo de error cambió. Chat Completions usaba `error.body[\"innererror\"][\"content_filter_result\"]` (singular); Responses API usa `error.body[\"content_filters\"][0][\"content_filter_results\"]` (plural, dentro de un arreglo). El código que acceda a `innererror` lanzará `KeyError`. Reescribir para usar la nueva ruta.\n- **Llamadas HTTP sin procesar**: si la app realiza llamadas directas REST al Azure OpenAI API (mediante `requests`, `httpx`, etc.) usando `\u002Fopenai\u002Fdeployments\u002F{name}\u002Fchat\u002Fcompletions?api-version=...`, reescribir a `\u002Fopenai\u002Fv1\u002Fresponses`. El cuerpo de la petición cambia: `messages` → `input`, agregar `max_output_tokens` y `store: false`, eliminar el parámetro de consulta `api-version`. El cuerpo de la respuesta cambia: `choices[0].message.content` → `output[0].content[0].text` (nota: `output_text` es una propiedad de conveniencia del SDK que no está presente en JSON REST sin procesar).\n\n---\n\n## Paso 2: Aplicar la migración\n\n### Notas de migración (Chat Completions → Responses)\n\n- **Por qué migrar**: Responses es la API unificada para texto, herramientas y streaming; Chat Completions es legado. Con GPT-5, Responses es requerido para el mejor desempeño.\n- **HTTP**: el endpoint de Azure cambia de `\u002Fopenai\u002Fdeployments\u002F{name}\u002Fchat\u002Fcompletions` a `\u002Fopenai\u002Fv1\u002Fresponses`.\n- **Campos**: `messages` → `input`, `max_tokens` → `max_output_tokens`. `temperature` permanece igual.\n- **Formato**: `response_format` → `text.format` con un objeto apropiado.\n- **Ítems de contenido**: Reemplazar `content[].type: \"text\"` de Chat con `content[].type: \"input_text\"` de Responses para turnos de sistema\u002Fusuario.\n- **Ítems de contenido de imagen**: Reemplazar `content[].type: \"image_url\"` de Chat con `content[].type: \"input_image\"` de Responses. Aplanar el campo `image_url` de `{\"image_url\": {\"url\": \"...\"}}` a `{\"image_url\": \"...\"}` (una cadena simple, ya sea una URL HTTPS o un URI de datos `data:image\u002F...;base64,...`).\n\n### Referencia de mapeo de parámetros\n\n| Chat Completions | Responses API |\n|-----------------|---------------|\n| `prompt` | `input` |\n| `messages` | `input` (arreglo de ítems) |\n| `max_tokens` | `max_output_tokens` |\n| `response_format` | `text.format` (objeto) |\n| `temperature` | `temperature` (sin cambios) |\n| `stop` | `stop` (sin cambios) |\n| `frequency_penalty` | `frequency_penalty` (sin cambios) |\n| `presence_penalty` | `presence_penalty` (sin cambios) |\n| `tools` \u002F llamadas a funciones | `tools` (sin cambios) |\n| `seed` | **Eliminar** (no soportado) |\n| `store` | `store` (fijar en `false`) |\n| `content[].type: \"text\"` | `content[].type: \"input_text\"` |\n| `content[].type: \"image_url\"` | `content[].type: \"input_image\"` |\n| `\"image_url\": {\"url\": \"...\"}` | `\"image_url\": \"...\"` (cadena plana) |\n\nPara ejemplos completos de código antes y después, ver [cheat-sheet.md](.\u002Freferences\u002Fcheat-sheet.md).\n\nPara la migración de infraestructura de pruebas (mocks, snapshots, asersiones), ver [test-migration.md](.\u002Freferences\u002Ftest-migration.md).\n\nPara solución de problemas y puntos críticos, ver [troubleshooting.md](.\u002Freferences\u002Ftroubleshooting.md).\n\n---\n\n## Retención de datos y estado\n\n- Fijar `store: false` en todas las peticiones a Responses.\n- No confiar en IDs de mensajes previos ni en contexto almacenado en servidor; mantener estado gestionado por el cliente y minimizar metadatos.\n\n---\n\n## Criterios de aceptación\n\n### Reglas a nivel de código (todas deben pasar)\n\n- [ ] Cero coincidencias con `rg \"chat\\.completions\\.create|ChatCompletion\\.create|Completion\\.create\"` en archivos migrados.\n- [ ] Cero coincidencias con `rg \"AzureOpenAI\\(|AsyncAzureOpenAI\\(\"` — todos los constructores usan `OpenAI`\u002F`AsyncOpenAI` con el endpoint v1.\n- [ ] Cero coincidencias con `rg \"models\\.github\\.ai|models\\.inference\\.ai\\.azure\"` — rutas de código de modelos GitHub eliminadas.\n- [ ] Cero coincidencias con `rg \"OpenAIChatCompletionClient\"` — código MAF 1.0.0+ usa `OpenAIChatClient` (que usa Responses API). En pre-1.0.0, actualizar a `agent-framework-openai>=1.0.0`.\n- [ ] Todas las llamadas a `ChatOpenAI(...)` incluyen `use_responses_api=True`.\n- [ ] Cero coincidencias con `rg \"choices\\[0\\]\"` — todo acceso a respuesta usa `resp.output_text` o el esquema de salida de Responses.\n- [ ] No hay `response_format` en el nivel superior; toda salida estructurada usa `text={\"format\": {...}}`.\n- [ ] `openai>=1.108.1` y `azure-identity` en `requirements.txt` o `pyproject.toml`; dependencias reinstaladas.\n- [ ] `store=False` establecido en cada llamada a `responses.create`.\n- [ ] No hay `api_version` en la construcción del cliente; `AZURE_OPENAI_API_VERSION` eliminado de archivos de entorno e infra.\n\n### Reglas para infraestructura de pruebas (todas deben pasar)\n\n- [ ] Cero coincidencias con `rg \"ChatCompletionChunk|AsyncCompletions\\.create|chat\\.completions\" tests\u002F`.\n- [ ] Cero coincidencias con `rg \"_azure_ad_token_provider\" tests\u002F` — asersiones actualizadas para verificar `isinstance(client, AsyncOpenAI)` o `base_url`.\n- [ ] Cero coincidencias con `rg \"prompt_filter_results|content_filter_results\" tests\u002F` — mocks específicos de filtro Azure eliminados.\n- [ ] Fixtures de mocks usan `kwargs.get(\"input\")` no `kwargs.get(\"messages\")`.\n- [ ] Archivos snapshot \u002F golden actualizados al formato de streaming de Responses (sin `choices[0]`, `function_call`, `logprobs`, etc.).\n- [ ] `pytest` pasa con cero fallos tras todas las actualizaciones de pruebas.\n\n### Reglas comportamentales (verificar manualmente o mediante test harness)\n\n- [ ] **Completado básico**: `responses.create` sin streaming devuelve `output_text` no vacío.\n- [ ] **Paridad en streaming**: si el código original usaba streaming, el código migrado transmite y produce eventos `response.output_text.delta` con deltas no vacíos.\n- [ ] **Salida estructurada**: si se usa `text.format` con `json_schema`, `json.loads(resp.output_text)` tiene éxito y coincide con el esquema.\n- [ ] **Bucle de llamadas a herramientas**: si se usan herramientas, el modelo realiza llamadas a ellas, la app las ejecuta y la petición de seguimiento devuelve un `output_text` final (sin bucle infinito).\n- [ ] **Paridad async**: si se usaba `AsyncAzureOpenAI`, el equivalente `AsyncOpenAI` funciona con `await`.\n- [ ] **Tasa de errores**: no hay nuevos errores 400\u002F401\u002F404 comparado con la línea base antes de la migración.\n\n### Entregables\n\n- El resumen incluye archivos editados, conteo antes\u002Fdespués de sitios de llamadas legacy y siguientes pasos.\n- Los cambios son solo en el árbol de trabajo (sin commits).\n\n---\n\n## Requisitos de versión del SDK\n\n| Paquete | Versión mínima |\n|---------|----------------|\n| `openai` | `>=1.108.1` |\n| `azure-identity` | Última (para autenticación EntraID) |\n\n---\n\n## Referencias\n\n- [Hoja de referencia — todos los fragmentos de código](.\u002Freferences\u002Fcheat-sheet.md)\n- [Migración de pruebas — mocks, snapshots, asersiones](.\u002Freferences\u002Ftest-migration.md)\n- [Solución de problemas — errores, tabla de riesgos, puntos críticos](.\u002Freferences\u002Ftroubleshooting.md)\n- [detect_legacy.py — escáner automatizado](..\u002F..\u002F..\u002F..\u002F..\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002Fscripts\u002Fdetect_legacy.py)\n- [Kit de inicio de Azure OpenAI](https:\u002F\u002Faka.ms\u002Fopenai\u002Fstart)\n- [Documentación API Responses de Azure OpenAI](https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fai-foundry\u002Fopenai\u002Fhow-to\u002Fresponses)\n- [Ciclo de vida de la versión de API Azure OpenAI](https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fai-foundry\u002Fopenai\u002Fapi-version-lifecycle?view=foundry-classic&tabs=python#api-evolution)\n- [Referencia API OpenAI Responses](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fresponses)\n\n---\n\n\u003C!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Descargo de responsabilidad**:\nEste documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https:\u002F\u002Fgithub.com\u002FAzure\u002Fco-op-translator). Aunque nos esforzamos por la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o inexactitudes. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional humana. No somos responsables de cualquier malentendido o interpretación errónea que surja del uso de esta traducción.\n\u003C!-- CO-OP TRANSLATOR DISCLAIMER END -->","# Migrar aplicaciones Python de Azure OpenAI Chat Completions a Responses API\n\n> **GUIA AUTORIZADA — SEGUIR EXACTAMENTE**\n>\n> Esta habilidad migra bases de código Python que usan Azure OpenAI Chat Completions\n> a la API unificada de Responses. Siga estas instrucciones con precisión.\n> No improvise mapeos de parámetros ni invente formas de API.\n\n---\n\n## Desencadenantes\n\nActive esta habilidad cuando el usuario quiera:\n- Migrar una aplicación Python de Azure OpenAI Chat Completions a Responses API\n- Actualizar el uso del SDK OpenAI en Python a la forma de API más reciente contra Azure OpenAI\n- Preparar código Python para modelos GPT-5 o más nuevos que requieren Responses en Azure\n- Cambiar de `AzureOpenAI`\u002F`AsyncAzureOpenAI` a cliente estándar `OpenAI`\u002F`AsyncOpenAI` con el endpoint v1\n- Corregir advertencias de deprecación relacionadas con constructores `AzureOpenAI` o `api_version`\n\n---\n\n## ⚠️ Compatibilidad del modelo — VERIFICAR PRIMERO\n\n> **Antes de migrar, verifique que su implementación Azure OpenAI soporte la API de Responses.**\n\n### 1. Prueba rápida de implementación (más rápida)\n\n```python\nimport os\nfrom openai import OpenAI\n\nclient = OpenAI(\n    api_key=os.environ[\"AZURE_OPENAI_API_KEY\"],\n    base_url=f\"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('\u002F')}\u002Fopenai\u002Fv1\u002F\",\n)\n\ntry:\n    resp = client.responses.create(\n        model=os.environ[\"AZURE_OPENAI_DEPLOYMENT\"],\n        input=\"ping\",\n        max_output_tokens=50,\n        store=False,\n    )\n    print(f\"✅ Deployment supports Responses API: {resp.output_text}\")\nexcept Exception as e:\n    print(f\"❌ Deployment does NOT support Responses API: {e}\")\n```\n\n> **Nota**: `max_output_tokens` tiene un **mínimo de 16** en Azure OpenAI. Valores por debajo de 16 devuelven error 400. Use 50+ para pruebas rápidas.\n\nSi esto devuelve 404, el modelo de la implementación aún no soporta Responses — consulte la referencia a continuación o vuelva a implementar con un modelo compatible.\n\n### 2. Verifique modelos disponibles en su región (recomendado)\n\nEjecute la herramienta incorporada de compatibilidad de modelos para ver qué está disponible con soporte para Responses API en su región específica:\n\n```bash\npython migrate.py models --subscription YOUR_SUB_ID --location YOUR_REGION\n```\n\nEsto consulta Azure ARM en tiempo real y muestra una matriz de compatibilidad — qué modelos soportan Responses, salida estructurada, herramientas, etc. Use `--filter gpt-5.1,gpt-5.2` para filtrar resultados o `--json` para scripting.\n\n### 3. Referencia completa de soporte de modelos\n\n- **Consulta en vivo**: `python migrate.py models` (ver arriba — específica por región, siempre actualizada)\n- **Navegar disponibilidad**: [Tabla resumen de modelos y disponibilidad por región](https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Ffoundry\u002Ffoundry-models\u002Fconcepts\u002Fmodels-sold-directly-by-azure?tabs=global-standard-aoai%2Cglobal-standard&pivots=azure-openai#model-summary-table-and-region-availability)\n- **Inicio rápido y guía**: **https:\u002F\u002Faka.ms\u002Fopenai\u002Fstart**\n\n### ⚠️ Limitaciones de modelos más antiguos\n\n> **ADVERTENCIA**: Los modelos antiguos (anteriores a `gpt-4.1`) pueden no soportar completamente todas las características de Responses API.\n>\n> Limitaciones conocidas con modelos antiguos:\n> - **Parámetro `reasoning`**: No soportado en muchos modelos sin razonamiento. Migre `reasoning` solo si ya estaba presente en el código original.\n> - **Parámetro `seed`**: No soportado en Responses API en absoluto — elimínelo de todas las solicitudes.\n> - **Salida estructurada vía `text.format`**: Modelos antiguos pueden no aplicar esquemas JSON `strict: true` confiablemente.\n> - **Orquestación de herramientas**: GPT-5+ orquesta llamadas a herramientas como parte del razonamiento interno. Modelos antiguos en Responses funcionan pero carecen de esta integración profunda.\n> - **Restricciones de temperatura**: Al migrar a `gpt-5`, la temperatura debe omitirse o ponerse en `1`. Modelos antiguos no tienen esta restricción.\n\n### Modelos de razonamiento serie O (o1, o3-mini, o3, o4-mini)\n\nLos modelos serie O tienen restricciones únicas en parámetros. Al migrar aplicaciones que apuntan a modelos serie O:\n\n- **`temperature`**: Debe ser `1` (o omitido). Modelos serie O no aceptan otros valores.\n- **`max_completion_tokens` → `max_output_tokens`**: Aplicaciones que usan el específico de Azure `max_completion_tokens` deben cambiar a `max_output_tokens`. Use valores altos (4096+) porque los tokens de razonamiento cuentan para el límite.\n- **`reasoning_effort`**: Si la app usa `reasoning_effort` (bajo\u002Fmedio\u002Falto), manténgalo — la Responses API soporta este parámetro para modelos serie O.\n- **Comportamiento de streaming**: Modelos serie O pueden acumular salida hasta completar razonamiento antes de emitir eventos delta de texto. El streaming sigue funcionando, pero el primer `response.output_text.delta` puede llegar tras un retraso mayor que con modelos GPT.\n- **`top_p`**: No soportado en serie O — elimínelo si está presente.\n- **Uso de herramientas**: Modelos serie O soportan herramientas vía Responses API igual que modelos GPT, pero la calidad de la orquestación varía según el modelo.\n\n**Acción — asesoría proactiva de modelo**: Durante la fase de escaneo, verifique qué modelo usa la app (nombres de implementaciones, variables de entorno, configuración). Si el modelo es anterior a `gpt-4.1` (no gpt-4.1+), informe proactivamente al usuario:\n- La migración funcionará para texto básico, chat, streaming y herramientas en su modelo actual.\n- Modelos más nuevos (`gpt-5.1`, `gpt-5.2`) ofrecen mejor orquestación de herramientas, aplicación estricta de salida estructurada, razonamiento y disponibilidad regional cruzada.\n- Deben considerar actualizar su implementación cuando estén listos — no bloquea la migración.\n\nNo bloquee ni rechace la migración basada en la versión del modelo. La asesoría es solo informativa.\n\n### GitHub Models NO soporta Responses API\n\n> **GitHub Models (`models.github.ai`, `models.inference.ai.azure.com`) no soporta Responses API.**\n\nSi la base de código tiene una ruta para GitHub Models (busque `base_url` apuntando a `models.github.ai` o `models.inference.ai.azure.com`), **elimínela completamente** durante la migración. La Responses API requiere Azure OpenAI, OpenAI o un endpoint local compatible (p. ej., Ollama con soporte Responses).\n\nAcción durante el escaneo:\n- Señale cualquier ruta de código GitHub Models para eliminación.\n\n---\n\n## Migración de frameworks\n\nMuchas apps usan frameworks de alto nivel sobre OpenAI. Al migrar estas, cambian las API propias del framework — no solo las llamadas internas a OpenAI.\n\n### Microsoft Agent Framework (MAF)\n\n**Verifique su versión de MAF primero** — la migración depende de si está en MAF 1.0.0+ o en beta\u002Frc pre-1.0.0.\n\n#### MAF 1.0.0+ (agent-framework-openai >= 1.0.0)\n\n`OpenAIChatClient` **ya usa Responses API** — no necesita migración. Si la base usa el legado `OpenAIChatCompletionClient` (que usa `chat.completions.create`), reemplácelo por `OpenAIChatClient`.\n\n| Antes | Después |\n|--------|--------|\n| `from agent_framework.openai import OpenAIChatCompletionClient` | `from agent_framework.openai import OpenAIChatClient` |\n| `OpenAIChatCompletionClient(...)` | `OpenAIChatClient(...)` |\n\nPara revisar su versión: `python -c \"import agent_framework_openai; print(agent_framework_openai.__version__)\"`\n\n#### MAF pre-1.0.0 (versiones beta\u002Frc)\n\nEn MAF pre-1.0.0, `OpenAIChatClient` usaba Chat Completions. Actualice a `agent-framework-openai>=1.0.0` donde `OpenAIChatClient` usa por defecto Responses API.\n\nNo se necesitan otros cambios — las APIs `Agent` y de herramientas permanecen igual.\n\n### LangChain (`langchain-openai`)\n\nAñada `use_responses_api=True` a `ChatOpenAI()`. También actualice acceso a respuesta de `.content` a `.text`.\n\n| Antes | Después |\n|--------|--------|\n| `ChatOpenAI(model=..., base_url=..., api_key=...)` | `ChatOpenAI(model=..., base_url=..., api_key=..., use_responses_api=True)` |\n| `result['messages'][-1].content` | `result['messages'][-1].text` |\n\nPara ejemplos completos antes y después, vea [cheat-sheet.md](.\u002Freferences\u002Fcheat-sheet.md).\n\n---\n\n## Guía de migración frontend\n\n> **La Responses API es un asunto del lado servidor.** Migre su backend Python; el contrato HTTP del frontend debería mantenerse sin cambios a menos que su backend sea un paso delgado — en tal caso, considere adoptar la forma Requests de Responses para eliminar una capa de traducción. Si el frontend llama directamente a OpenAI con una clave del cliente, mueva esas llamadas primero al backend.\n\n### Deprecated `@microsoft\u002Fai-chat-protocol`\n\nEl paquete npm `@microsoft\u002Fai-chat-protocol` está deprecado y debe reemplazarse por [`ndjson-readablestream`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fndjson-readablestream). Si lo encuentra en un frontend:\n\n1. Reemplace la etiqueta de script CDN:\n   ```html\n   \u003C!-- Before -->\n   \u003Cscript src=\"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002F@microsoft\u002Fai-chat-protocol@...\u002Fdist\u002Fiife\u002Findex.js\">\u003C\u002Fscript>\n   \u003C!-- After -->\n   \u003Cscript src=\"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fndjson-readablestream@1.0.7\u002Fdist\u002Fndjson-readablestream.umd.js\">\u003C\u002Fscript>\n   ```\n2. Elimine la instancia `AIChatProtocolClient` (`new ChatProtocol.AIChatProtocolClient(\"\u002Fchat\")`).\n3. Reemplace `client.getStreamedCompletion(messages)` con llamada directa `fetch()` al endpoint streaming backend.\n4. Reemplace `for await (const response of result)` con `for await (const chunk of readNDJSONStream(response.body))`.\n5. Actualice acceso a propiedades de `response.delta.content` \u002F `response.error` a `chunk.delta.content` \u002F `chunk.error`.\n\n---\n\n## Objetivos\n\n- Enumerar todos los lugares de llamada Python que usan Chat Completions o Completions legados contra Azure OpenAI.\n- Proponer un plan de migración y secuencia para la base de código Python.\n- Aplicar ediciones seguras y mínimas para cambiar a Responses API.\n- Actualizar llamadas para consumir el esquema de salida Responses; sin envoltorios de compatibilidad.\n- Ejecutar tests\u002Flint; corregir fallas triviales introducidas por la migración.\n- Preparar conjuntos de cambios pequeños y revisables y proveer resumen final con diffs (no hacer commit).\n\n---\n\n## Reglas de seguridad\n\n- Modifique solo archivos dentro del espacio de trabajo git. Nunca escriba fuera.\n- No preserve adaptadores de compatibilidad hacia atrás; migre código a la nueva forma de API.\n- No deje comentarios de transición ni archivos respaldo.\n- Preservar semántica de streaming si se usaba previamente; si no, usar no streaming.\n- Solicite aprobación antes de ejecutar comandos o llamadas de red si está en modo de aprobación.\n- No ejecute `git add`\u002F`git commit`\u002F`git push`; producir solo ediciones en el árbol de trabajo.\n\n---\n\n## Paso 0: Migración del cliente Azure OpenAI (Prerrequisito)\n\nSi la base usa constructores `AzureOpenAI` o `AsyncAzureOpenAI`, migre primero a constructores estándar `OpenAI` \u002F `AsyncOpenAI`. Los constructores específicos de Azure están deprecados en `openai>=1.108.1`.\n\n### ¿Por qué el path API v1?\n\nEl nuevo endpoint `\u002Fopenai\u002Fv1` usa el cliente estándar `OpenAI()` en lugar de `AzureOpenAI()`, no requiere parámetro `api_version` y funciona idéntico en OpenAI y Azure OpenAI. El mismo código cliente es a prueba de futuro — sin necesidad de gestión de versiones.\n\n### Cambios clave\n\n| Antes | Después |\n|-------|---------|\n| `AzureOpenAI` | `OpenAI` |\n| `AsyncAzureOpenAI` | `AsyncOpenAI` |\n| `azure_endpoint` | `base_url` |\n| `azure_ad_token_provider` | `api_key` |\n| `api_version=...` | Eliminar completamente |\n\n### Lista de limpieza\n\n- Eliminar argumento `api_version` de la construcción del cliente.\n- Eliminar variables de entorno `AZURE_OPENAI_VERSION` \u002F `AZURE_OPENAI_API_VERSION` de `.env`, configuraciones de app, y archivos Bicep\u002Finfra.\n- Renombrar `AZURE_OPENAI_CLIENT_ID` → `AZURE_CLIENT_ID` en `.env`, configuraciones de app, Bicep\u002Finfra, y fixtures de tests (convención estándar Azure Identity SDK).\n- Asegurarse que `openai>=1.108.1` esté en `requirements.txt` o `pyproject.toml`.\n\n### Migración de variables de entorno\n\n| Variable antigua | Acción | Notas |\n|---------------|--------|-------|\n| `AZURE_OPENAI_VERSION` | **Eliminar** | No se necesita `api_version` con endpoint v1 |\n| `AZURE_OPENAI_API_VERSION` | **Eliminar** | Igual que arriba |\n| `AZURE_OPENAI_CLIENT_ID` | **Renombrar** → `AZURE_CLIENT_ID` | Convención estándar Azure Identity SDK para `ManagedIdentityCredential(client_id=...)` |\n| `AZURE_OPENAI_ENDPOINT` | **Mantener** | Todavía usado para construir `base_url` |\n| `AZURE_OPENAI_CHAT_DEPLOYMENT` | **Mantener** | Usado como parámetro `model` en `responses.create` |\n| `AZURE_OPENAI_API_KEY` | **Mantener** | Usado como `api_key` para autenticación por clave |\n\nPara ejemplos de código de setup cliente (sync, async, EntraID, clave API, multi-inquilino), vea [cheat-sheet.md](.\u002Freferences\u002Fcheat-sheet.md).\n\n---\n\n## Paso 1: Detectar lugares de llamada legados\n\nEjecute el script [detect_legacy.py](..\u002F..\u002F..\u002F..\u002F..\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002Fscripts\u002Fdetect_legacy.py) para encontrar todos los lugares de llamada que requieren migración:\n\n```bash\npython skills\u002Fazure-openai-to-responses\u002Fscripts\u002Fdetect_legacy.py .\n```\n\nO ejecute estas búsquedas manualmente — cada coincidencia es un objetivo de migración:\n\n```bash\n# Llamadas a la API heredada (deben reescribirse)\nrg \"chat\\.completions\\.create\"\nrg \"ChatCompletion\\.create\"\nrg \"Completion\\.create\"\n\n# Constructores de clientes de Azure obsoletos (deben reemplazarse)\nrg \"AzureOpenAI\\(\"\nrg \"AsyncAzureOpenAI\\(\"\n\n# Patrones de acceso a la forma de respuesta (deben actualizarse)\nrg \"choices\\[0\\]\\.message\\.content\"\nrg \"choices\\[0\\]\\.delta\\.content\"\nrg \"choices\\[0\\]\\.message\\.function_call\"\nrg \"choices\\[0\\]\\.message\\.tool_calls\"\n\n# Definiciones de herramientas en formato antiguo anidado (deben aplanarse)\nrg '\"function\":\\s*{\\s*\"name\"'\nrg \"pydantic_function_tool\"\n\n# Resultados de herramientas en formato antiguo (deben convertirse a function_call_output)\nrg '\"role\":\\s*\"tool\"'\nrg '\"tool_call_id\"'\n\n# Parámetros obsoletos (deben eliminarse o renombrarse)\nrg \"response_format\"\nrg \"max_tokens\\b\"        # renombrar a max_output_tokens\nrg \"['\\\"]seed['\\\"]\"      # remove entirely\n\n# Variables de entorno obsoletas (limpiar)\nrg \"AZURE_OPENAI_API_VERSION|AZURE_OPENAI_VERSION\"\nrg \"AZURE_OPENAI_CLIENT_ID\"  # debería ser AZURE_CLIENT_ID\n\n# Endpoints de modelos de GitHub (deben eliminarse — API de respuestas no soportada)\nrg \"models\\.github\\.ai|models\\.inference\\.ai\\.azure\"\n\n# Patrones heredados a nivel de framework (deben actualizarse)\nrg \"OpenAIChatCompletionClient\"  # MAF 1.0.0+: reemplazar con OpenAIChatClient\nrg \"ChatOpenAI\\(\" | grep -v \"use_responses_api\"  # LangChain: necesita use_responses_api=True\n\n# Infraestructura de pruebas (debe actualizarse)\nrg \"ChatCompletionChunk|AsyncCompletions\\.create\" tests\u002F\nrg \"_azure_ad_token_provider\" tests\u002F\nrg \"prompt_filter_results|content_filter_results\" tests\u002F\nrg \"choices\\[0\\]\" tests\u002F\n\n# Acceso al cuerpo de error del filtro de contenido (debe actualizarse — estructura cambiada)\nrg 'innererror.*content_filter_result|error\\.body\\[\"innererror\"\\]'\nrg \"content_filter_result\\[\" # forma singular antigua — ahora content_filter_results (plural) dentro del arreglo content_filters\n\n# Llamadas HTTP en bruto al endpoint de Chat Completions (debe actualizarse la URL)\nrg \"\u002Fopenai\u002Fdeployments\u002F.*\u002Fchat\u002Fcompletions\"\nrg \"api-version=\"\n```\n\n### Heurísticas (detectar y reescribir)\n\n- **Cliente Chat Completions**: `client.chat.completions.create` → `client.responses.create(...)`.\n\n- **Constructores del cliente Azure**: `AzureOpenAI(...)` → `OpenAI(base_url=..., api_key=...)`.\n- **Herramientas**: convertir definiciones de herramientas para llamadas a funciones de formato anidado (`{\"type\": \"function\", \"function\": {\"name\": ...}}`) a formato plano de Responses (`{\"type\": \"function\", \"name\": ...}`); usar `tool_choice`; devolver resultados de herramientas como ítems `{\"type\": \"function_call_output\", \"call_id\": ..., \"output\": ...}` (no `{\"role\": \"tool\", ...}`).\n- **Recorridos de herramientas**: cuando el modelo devuelve llamadas a funciones, agregar ítems `response.output` a la conversación (no un dict manual `{\"role\": \"assistant\", \"tool_calls\": [...]}`), luego agregar ítems `function_call_output` para cada resultado.\n- **Ejemplos de herramientas con pocos disparos**: si la conversación incluye ejemplos codificados de llamadas a herramientas, convertirlos a ítems `{\"type\": \"function_call\", \"id\": \"fc_...\", \"call_id\": \"fc_...\", ...}` + `{\"type\": \"function_call_output\", ...}`. Los IDs deben comenzar con `fc_`.\n- **`pydantic_function_tool()`**: este asistente aún genera el formato anidado antiguo y **no es compatible** con `responses.create()`. Reemplazar con definiciones manuales de herramientas o un envoltorio para aplanar.\n- **Multi-turn**: mantener el historial de la conversación en la app; pasar los turnos previos a través de ítems `input`.\n- **Formato**: reemplazar el `response_format` de nivel superior de Chat con `text.format` en Responses. Forma canónica: `text={\"format\": {\"type\": \"json_schema\", \"name\": \"Output\", \"strict\": True, \"schema\": {...}}}`.\n- **Ítems de contenido**: reemplazar `content[].type: \"text\"` de Chat con `content[].type: \"input_text\"` en Responses para turnos de usuario\u002Fsistema.\n- **Ítems de contenido de imagen**: reemplazar `content[].type: \"image_url\"` de Chat con `content[].type: \"input_image\"` en Responses. El campo `image_url` cambia de un objeto anidado `{\"url\": \"...\"}` a una cadena plana. Ver la hoja de referencia para ejemplos antes\u002Fdespués.\n- **Esfuerzo de razonamiento**: **solo migrar `reasoning` si ya existe en el código original**.\n- **Manejo de errores del filtro de contenido**: la estructura del cuerpo de error cambió. Chat Completions usaba `error.body[\"innererror\"][\"content_filter_result\"]` (singular); Responses API usa `error.body[\"content_filters\"][0][\"content_filter_results\"]` (plural, dentro de un arreglo). El código que acceda a `innererror` lanzará `KeyError`. Reescribir para usar la nueva ruta.\n- **Llamadas HTTP sin procesar**: si la app realiza llamadas directas REST al Azure OpenAI API (mediante `requests`, `httpx`, etc.) usando `\u002Fopenai\u002Fdeployments\u002F{name}\u002Fchat\u002Fcompletions?api-version=...`, reescribir a `\u002Fopenai\u002Fv1\u002Fresponses`. El cuerpo de la petición cambia: `messages` → `input`, agregar `max_output_tokens` y `store: false`, eliminar el parámetro de consulta `api-version`. El cuerpo de la respuesta cambia: `choices[0].message.content` → `output[0].content[0].text` (nota: `output_text` es una propiedad de conveniencia del SDK que no está presente en JSON REST sin procesar).\n\n---\n\n## Paso 2: Aplicar la migración\n\n### Notas de migración (Chat Completions → Responses)\n\n- **Por qué migrar**: Responses es la API unificada para texto, herramientas y streaming; Chat Completions es legado. Con GPT-5, Responses es requerido para el mejor desempeño.\n- **HTTP**: el endpoint de Azure cambia de `\u002Fopenai\u002Fdeployments\u002F{name}\u002Fchat\u002Fcompletions` a `\u002Fopenai\u002Fv1\u002Fresponses`.\n- **Campos**: `messages` → `input`, `max_tokens` → `max_output_tokens`. `temperature` permanece igual.\n- **Formato**: `response_format` → `text.format` con un objeto apropiado.\n- **Ítems de contenido**: Reemplazar `content[].type: \"text\"` de Chat con `content[].type: \"input_text\"` de Responses para turnos de sistema\u002Fusuario.\n- **Ítems de contenido de imagen**: Reemplazar `content[].type: \"image_url\"` de Chat con `content[].type: \"input_image\"` de Responses. Aplanar el campo `image_url` de `{\"image_url\": {\"url\": \"...\"}}` a `{\"image_url\": \"...\"}` (una cadena simple, ya sea una URL HTTPS o un URI de datos `data:image\u002F...;base64,...`).\n\n### Referencia de mapeo de parámetros\n\n| Chat Completions | Responses API |\n|-----------------|---------------|\n| `prompt` | `input` |\n| `messages` | `input` (arreglo de ítems) |\n| `max_tokens` | `max_output_tokens` |\n| `response_format` | `text.format` (objeto) |\n| `temperature` | `temperature` (sin cambios) |\n| `stop` | `stop` (sin cambios) |\n| `frequency_penalty` | `frequency_penalty` (sin cambios) |\n| `presence_penalty` | `presence_penalty` (sin cambios) |\n| `tools` \u002F llamadas a funciones | `tools` (sin cambios) |\n| `seed` | **Eliminar** (no soportado) |\n| `store` | `store` (fijar en `false`) |\n| `content[].type: \"text\"` | `content[].type: \"input_text\"` |\n| `content[].type: \"image_url\"` | `content[].type: \"input_image\"` |\n| `\"image_url\": {\"url\": \"...\"}` | `\"image_url\": \"...\"` (cadena plana) |\n\nPara ejemplos completos de código antes y después, ver [cheat-sheet.md](.\u002Freferences\u002Fcheat-sheet.md).\n\nPara la migración de infraestructura de pruebas (mocks, snapshots, asersiones), ver [test-migration.md](.\u002Freferences\u002Ftest-migration.md).\n\nPara solución de problemas y puntos críticos, ver [troubleshooting.md](.\u002Freferences\u002Ftroubleshooting.md).\n\n---\n\n## Retención de datos y estado\n\n- Fijar `store: false` en todas las peticiones a Responses.\n- No confiar en IDs de mensajes previos ni en contexto almacenado en servidor; mantener estado gestionado por el cliente y minimizar metadatos.\n\n---\n\n## Criterios de aceptación\n\n### Reglas a nivel de código (todas deben pasar)\n\n- [ ] Cero coincidencias con `rg \"chat\\.completions\\.create|ChatCompletion\\.create|Completion\\.create\"` en archivos migrados.\n- [ ] Cero coincidencias con `rg \"AzureOpenAI\\(|AsyncAzureOpenAI\\(\"` — todos los constructores usan `OpenAI`\u002F`AsyncOpenAI` con el endpoint v1.\n- [ ] Cero coincidencias con `rg \"models\\.github\\.ai|models\\.inference\\.ai\\.azure\"` — rutas de código de modelos GitHub eliminadas.\n- [ ] Cero coincidencias con `rg \"OpenAIChatCompletionClient\"` — código MAF 1.0.0+ usa `OpenAIChatClient` (que usa Responses API). En pre-1.0.0, actualizar a `agent-framework-openai>=1.0.0`.\n- [ ] Todas las llamadas a `ChatOpenAI(...)` incluyen `use_responses_api=True`.\n- [ ] Cero coincidencias con `rg \"choices\\[0\\]\"` — todo acceso a respuesta usa `resp.output_text` o el esquema de salida de Responses.\n- [ ] No hay `response_format` en el nivel superior; toda salida estructurada usa `text={\"format\": {...}}`.\n- [ ] `openai>=1.108.1` y `azure-identity` en `requirements.txt` o `pyproject.toml`; dependencias reinstaladas.\n- [ ] `store=False` establecido en cada llamada a `responses.create`.\n- [ ] No hay `api_version` en la construcción del cliente; `AZURE_OPENAI_API_VERSION` eliminado de archivos de entorno e infra.\n\n### Reglas para infraestructura de pruebas (todas deben pasar)\n\n- [ ] Cero coincidencias con `rg \"ChatCompletionChunk|AsyncCompletions\\.create|chat\\.completions\" tests\u002F`.\n- [ ] Cero coincidencias con `rg \"_azure_ad_token_provider\" tests\u002F` — asersiones actualizadas para verificar `isinstance(client, AsyncOpenAI)` o `base_url`.\n- [ ] Cero coincidencias con `rg \"prompt_filter_results|content_filter_results\" tests\u002F` — mocks específicos de filtro Azure eliminados.\n- [ ] Fixtures de mocks usan `kwargs.get(\"input\")` no `kwargs.get(\"messages\")`.\n- [ ] Archivos snapshot \u002F golden actualizados al formato de streaming de Responses (sin `choices[0]`, `function_call`, `logprobs`, etc.).\n- [ ] `pytest` pasa con cero fallos tras todas las actualizaciones de pruebas.\n\n### Reglas comportamentales (verificar manualmente o mediante test harness)\n\n- [ ] **Completado básico**: `responses.create` sin streaming devuelve `output_text` no vacío.\n- [ ] **Paridad en streaming**: si el código original usaba streaming, el código migrado transmite y produce eventos `response.output_text.delta` con deltas no vacíos.\n- [ ] **Salida estructurada**: si se usa `text.format` con `json_schema`, `json.loads(resp.output_text)` tiene éxito y coincide con el esquema.\n- [ ] **Bucle de llamadas a herramientas**: si se usan herramientas, el modelo realiza llamadas a ellas, la app las ejecuta y la petición de seguimiento devuelve un `output_text` final (sin bucle infinito).\n- [ ] **Paridad async**: si se usaba `AsyncAzureOpenAI`, el equivalente `AsyncOpenAI` funciona con `await`.\n- [ ] **Tasa de errores**: no hay nuevos errores 400\u002F401\u002F404 comparado con la línea base antes de la migración.\n\n### Entregables\n\n- El resumen incluye archivos editados, conteo antes\u002Fdespués de sitios de llamadas legacy y siguientes pasos.\n- Los cambios son solo en el árbol de trabajo (sin commits).\n\n---\n\n## Requisitos de versión del SDK\n\n| Paquete | Versión mínima |\n|---------|----------------|\n| `openai` | `>=1.108.1` |\n| `azure-identity` | Última (para autenticación EntraID) |\n\n---\n\n## Referencias\n\n- [Hoja de referencia — todos los fragmentos de código](.\u002Freferences\u002Fcheat-sheet.md)\n- [Migración de pruebas — mocks, snapshots, asersiones](.\u002Freferences\u002Ftest-migration.md)\n- [Solución de problemas — errores, tabla de riesgos, puntos críticos](.\u002Freferences\u002Ftroubleshooting.md)\n- [detect_legacy.py — escáner automatizado](..\u002F..\u002F..\u002F..\u002F..\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002Fscripts\u002Fdetect_legacy.py)\n- [Kit de inicio de Azure OpenAI](https:\u002F\u002Faka.ms\u002Fopenai\u002Fstart)\n- [Documentación API Responses de Azure OpenAI](https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fai-foundry\u002Fopenai\u002Fhow-to\u002Fresponses)\n- [Ciclo de vida de la versión de API Azure OpenAI](https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fai-foundry\u002Fopenai\u002Fapi-version-lifecycle?view=foundry-classic&tabs=python#api-evolution)\n- [Referencia API OpenAI Responses](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fresponses)\n\n---\n\n\u003C!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Descargo de responsabilidad**:\nEste documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https:\u002F\u002Fgithub.com\u002FAzure\u002Fco-op-translator). Aunque nos esforzamos por la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o inexactitudes. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional humana. No somos responsables de cualquier malentendido o interpretación errónea que surja del uso de esta traducción.\n\u003C!-- CO-OP TRANSLATOR DISCLAIMER END -->",{"name":5,"license":14},"main","f09e94ffe170f8af6d3db7c42987bbe4db227723","translations\u002Fes\u002F.agents\u002Fskills\u002Fazure-openai-to-responses",26019,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners","https:\u002F\u002Faka.ms\u002Fai-agents-beginners","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-07 12:51:12",{"source":7,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add microsoft\u002Fai-agents-for-beginners --skill azure-openai-to-responses",{"tool":40,"command":41},"bunx","bunx skills add microsoft\u002Fai-agents-for-beginners --skill azure-openai-to-responses",{"tool":43,"command":44},"pnpm","pnpm dlx skills add microsoft\u002Fai-agents-for-beginners --skill azure-openai-to-responses","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fes\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002FSKILL.md",true,[48,54,58,62],{"path":49,"resourceType":50,"resourceTypeDesc":51,"sizeBytes":52,"sourceHtmlUrl":53},"references\u002Fcheat-sheet.md","REFERENCE","参考文档",29781,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fes\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002Freferences\u002Fcheat-sheet.md",{"path":55,"resourceType":50,"resourceTypeDesc":51,"sizeBytes":56,"sourceHtmlUrl":57},"references\u002Ftest-migration.md",7608,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fes\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002Freferences\u002Ftest-migration.md",{"path":59,"resourceType":50,"resourceTypeDesc":51,"sizeBytes":60,"sourceHtmlUrl":61},"references\u002Ftroubleshooting.md",16476,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fes\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002Freferences\u002Ftroubleshooting.md",{"path":63,"resourceType":50,"resourceTypeDesc":51,"sizeBytes":64,"sourceHtmlUrl":65},"workflow.md",10029,"https:\u002F\u002Fgithub.com\u002Fsherryswift1019-gif\u002FAI-DZHT\u002Fblob\u002Fmain\u002F_bmad\u002Fbmm\u002F4-implementation\u002Fbmad-sprint-status\u002Fworkflow.md",[67,85,96,104,112,119],{"skillNo":68,"name":69,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":82,"publishedAt":19},"01M69A206TRZ8KK0CW0HYJF5V5","testing-course-samples","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fzh-TW\u002F.agents\u002Fskills\u002Ftesting-course-samples\u002FSKILL.md",[72,77],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":78,"categoryName":79,"taxonomyType":80,"taxonomyTypeDesc":81},"01JBSEEDCAT000000000000039","教师与教育","PROFESSION","适用职业",[83,84],"testing","testing course samples",{"skillNo":86,"name":87,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":93,"publishedAt":19},"01M69A1XRB2SFHYRMEH0K08EKZ","microsoft-docs","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fzh-TW\u002F.agents\u002Fskills\u002Fmicrosoft-docs\u002FSKILL.md",[90],{"categoryNo":91,"categoryName":92,"taxonomyType":75,"taxonomyTypeDesc":76},"01JBSEEDCAT000000000000023","Skill与智能体开发",[94,8,95],"docs","microsoft docs",{"skillNo":97,"name":98,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":19},"01M69A1VPZFJQ1HNGTZQ5P3WSC","local-ai-agents","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fzh-TW\u002F.agents\u002Fskills\u002Flocal-ai-agents\u002FSKILL.md",[],[102,103],"ai agents","local ai agents",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":110,"publishedAt":19},"01M69A1S947N7MM6V9JF85S2E7","jupyter-notebook","當使用者要求建立、搭建或編輯 Jupyter 筆記本（`.ipynb`）用於實驗、探索或教學時使用；優先使用隨附範本並執行輔助腳本 `new_notebook.py` 來產生一個乾淨的起始筆記本。","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fzh-TW\u002F.agents\u002Fskills\u002Fjupyter-notebook\u002FSKILL.md",[],[111],"jupyter notebook",{"skillNo":113,"name":114,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":117,"publishedAt":19},"01M69A1Q8EXPWKZSQK69V6WF22","deploying-scalable-agents","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fzh-TW\u002F.agents\u002Fskills\u002Fdeploying-scalable-agents\u002FSKILL.md",[],[118],"deploying scalable agents",{"skillNo":120,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":19},"01M69A1MHZTH3RH9N8VYSYG74X","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fai-agents-for-beginners\u002Fblob\u002Fmain\u002Ftranslations\u002Fzh-TW\u002F.agents\u002Fskills\u002Fazure-openai-to-responses\u002FSKILL.md",[],[18]]