Skip to content

Commit f82066d

Browse files
committed
Add AGENTS.md and missing translations
1 parent 23fc37b commit f82066d

16 files changed

Lines changed: 2713 additions & 15 deletions
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
name: update_translations
3+
description: Use this prompt to update the Spanish translations in the repo.
4+
model: GPT-5.2 (copilot)
5+
---
6+
7+
Update the Spanish translations in the repo according to the guidelines in AGENTS.md. Ensure there are spanish equivalents of each english example. Make sure to keep the translations consistent with the original content and maintain the technical accuracy of the code.

AGENTS.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Instructions for coding agents
2+
3+
This repository contains many examples of using the Microsoft Agent Framework in Python (agent-framework), sometimes abbreviated as MAF.
4+
5+
The agent-framework GitHub repo is here:
6+
https://github.com/microsoft/agent-framework
7+
It contains both Python and .NET agent framework code, but we are only using the Python packages in this repo.
8+
9+
MAF is changing rapidly still, so we sometimes need to check the repo changelog and issues to see if there are any breaking changes that might affect our code.
10+
The Python changelog is here:
11+
https://github.com/microsoft/agent-framework/blob/main/python/CHANGELOG.md
12+
13+
MAF documentation is available on Microsoft Learn here:
14+
https://learn.microsoft.com/agent-framework/
15+
When available, the MS Learn MCP server can be used to explore the documentation, ask questions, and get code examples.
16+
17+
## Spanish translations
18+
19+
There are Spanish equivalents of each example in /examples/spanish.
20+
21+
Each example .py file should have a corresponding _spanish.py file that is the translation of the original, but with the same code. Here's a guide on what should be translated vs. what should be left in English:
22+
23+
* Comments: Spanish
24+
* Docstrings: Spanish
25+
* System prompts (agent instructions): Spanish
26+
* Tool descriptions (metadata like description=): English
27+
* Parameter descriptions (Field(description=...)): English
28+
* Identifiers (functions/classes/vars): English
29+
* User-facing output/data (e.g., example responses, sample values): Spanish
30+
* HITL control words: bilingual (approve/aprobar, exit/salir)
31+
32+
Use informal (tuteo) LATAM Spanish, tu not usted, puedes not podes, etc. The content is technical so if a word is best kept in English, then do so.
33+
34+
The /examples/spanish/README.md corresponds to the root README.md and should be kept in sync with it, but translated to Spanish.

examples/spanish/README.md

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ Una opción relacionada es VS Code Dev Containers, que abrirá el proyecto en tu
5959
3. En la ventana de VS Code que se abre, una vez que aparezcan los archivos del proyecto (esto puede tardar varios minutos), abre una ventana de terminal.
6060
4. Continúa con los pasos para ejecutar los ejemplos
6161

62+
El dev container incluye un servidor Redis, que se usa en el ejemplo `agent_history_redis.py`.
63+
6264
### Entorno local
6365

6466
1. Asegúrate de tener instaladas las siguientes herramientas:
@@ -80,6 +82,12 @@ Una opción relacionada es VS Code Dev Containers, que abrirá el proyecto en tu
8082
uv sync
8183
```
8284

85+
4. *Opcional:* Para ejecutar el ejemplo `agent_history_redis.py`, necesitas un servidor Redis corriendo localmente:
86+
87+
```shell
88+
docker run -d -p 6379:6379 redis:7-alpine
89+
```
90+
8391
## Configurar proveedores de modelos
8492

8593
Estos ejemplos se pueden ejecutar con Azure AI Foundry, OpenAI.com o GitHub Models, dependiendo de las variables de entorno que configures. Todos los scripts hacen referencia a las variables de entorno de un archivo `.env`, y se proporciona un archivo de ejemplo `.env.sample`. Las instrucciones específicas de cada proveedor se encuentran a continuación.
@@ -163,19 +171,21 @@ Puedes ejecutar los ejemplos en este repositorio ejecutando los scripts en el di
163171

164172
| Ejemplo | Descripción |
165173
| ------- | ----------- |
166-
| [agent_basic.py](agent_basic.py) | Usa Agent Framework para crear un agente informativo básico. |
167-
| [agent_tool.py](agent_tool.py) | Usa Agent Framework para crear un agente con una única herramienta de clima. |
168-
| [agent_tools.py](agent_tools.py) | Usa Agent Framework para crear un agente planificador de fin de semana con múltiples herramientas. |
169-
| [agent_supervisor.py](agent_supervisor.py) | Usa Agent Framework con un supervisor que orquesta subagentes de actividades y recetas. |
170-
| [workflow_magenticone.py](workflow_magenticone.py) | Usa Agent Framework para crear un flujo de trabajo multi-agente MagenticOne. |
171-
| [workflow_hitl.py](workflow_hitl.py) | Usa Agent Framework con human-in-the-loop (HITL) para confirmar o editar respuestas. |
172-
| [agent_middleware.py](agent_middleware.py) | Usa Agent Framework con middleware de agente, chat y funciones para registro, temporización y bloqueo. |
174+
| [agent_basic.py](agent_basic.py) | Un agente informativo básico. |
175+
| [agent_tool.py](agent_tool.py) | Un agente con una sola herramienta de clima. |
176+
| [agent_tools.py](agent_tools.py) | Un agente planificador de fin de semana con múltiples herramientas. |
177+
| [agent_session.py](agent_session.py) | Sesiones en memoria para conversaciones multi-turno con memoria entre mensajes. |
178+
| [agent_history_redis.py](agent_history_redis.py) | Historial de chat persistente con Redis para conversación que sobrevive reinicios. |
179+
| [agent_supervisor.py](agent_supervisor.py) | Un supervisor que orquesta subagentes de actividades y recetas. |
180+
| [workflow_magenticone.py](workflow_magenticone.py) | Un workflow multi-agente MagenticOne. |
181+
| [workflow_hitl.py](workflow_hitl.py) | Human-in-the-loop (HITL) para agentes con herramientas con feedback humano. |
182+
| [agent_middleware.py](agent_middleware.py) | Middleware de agente, chat y funciones para logging, timing y bloqueo. |
173183
| [agent_knowledge_sqlite.py](agent_knowledge_sqlite.py) | Recuperación de conocimiento (RAG) usando un proveedor de contexto personalizado con SQLite FTS5. |
174184
| [agent_knowledge_postgres.py](agent_knowledge_postgres.py) | Recuperación de conocimiento (RAG) con búsqueda híbrida en PostgreSQL (pgvector + texto completo) usando Reciprocal Rank Fusion. |
175-
| [agent_mcp_remote.py](agent_mcp_remote.py) | Un agente que usa un servidor MCP remoto (Microsoft Learn) para búsqueda de documentación. |
176-
| [agent_mcp_local.py](agent_mcp_local.py) | Un agente conectado a un servidor MCP local (ej. para registro de gastos). |
177-
| [openai_tool_calling.py](openai_tool_calling.py) | Llamadas a funciones con el SDK de OpenAI de bajo nivel, mostrando despacho manual de herramientas. |
178-
| [workflow_basic.py](workflow_basic.py) | Usa Agent Framework para crear un agente basado en flujo de trabajo. |
185+
| [agent_mcp_remote.py](agent_mcp_remote.py) | Un agente usando un servidor MCP remoto (Microsoft Learn) para búsqueda de documentación. |
186+
| [agent_mcp_local.py](agent_mcp_local.py) | Un agente conectado a un servidor MCP local (p. ej. para registro de gastos). |
187+
| [openai_tool_calling.py](openai_tool_calling.py) | Llamadas a herramientas con el SDK de OpenAI de bajo nivel, mostrando despacho manual de herramientas. |
188+
| [workflow_basic.py](workflow_basic.py) | Un agente basado en workflows. |
179189
| [agent_otel_aspire.py](agent_otel_aspire.py) | Un agente con trazas, métricas y logs estructurados de OpenTelemetry exportados al [Aspire Dashboard](https://aspire.dev/dashboard/standalone/). |
180190

181191
## Usar el Aspire Dashboard para telemetría
@@ -184,9 +194,9 @@ El ejemplo [agent_otel_aspire.py](agent_otel_aspire.py) puede exportar trazas, m
184194

185195
### En GitHub Codespaces / Dev Containers
186196

187-
El Aspire Dashboard se ejecuta automaticamente como un servicio junto al dev container. No necesitas configuracion adicional.
197+
El Aspire Dashboard se ejecuta automáticamente como un servicio junto al dev container. No necesitas configuración adicional.
188198

189-
1. La variable de entorno `OTEL_EXPORTER_OTLP_ENDPOINT` ya esta configurada por el dev container.
199+
1. La variable de entorno `OTEL_EXPORTER_OTLP_ENDPOINT` ya está configurada por el dev container.
190200

191201
2. Ejecuta el ejemplo:
192202

@@ -227,13 +237,13 @@ Si ejecutas localmente sin Dev Containers, necesitas iniciar el Aspire Dashboard
227237

228238
4. Abre el dashboard en <http://localhost:18888> y explora.
229239

230-
5. Cuando termines, deten el dashboard:
240+
5. Cuando termines, detén el dashboard:
231241

232242
```sh
233243
docker stop aspire-dashboard
234244
```
235245

236-
Para la guia completa de Python + Aspire, consulta [Usar el Aspire Dashboard con apps de Python](https://aspire.dev/dashboard/standalone-for-python/).
246+
Para la guía completa de Python + Aspire, consulta [Usar el Aspire Dashboard con apps de Python](https://aspire.dev/dashboard/standalone-for-python/).
237247

238248
## Recursos
239249

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import asyncio
2+
import logging
3+
import os
4+
import random
5+
import uuid
6+
from typing import Annotated
7+
8+
from agent_framework import Agent, tool
9+
from agent_framework.openai import OpenAIChatClient
10+
from agent_framework.redis import RedisHistoryProvider
11+
from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider
12+
from dotenv import load_dotenv
13+
from pydantic import Field
14+
from rich import print
15+
from rich.logging import RichHandler
16+
17+
# Configurar logging
18+
handler = RichHandler(show_path=False, rich_tracebacks=True, show_level=False)
19+
logging.basicConfig(level=logging.WARNING, handlers=[handler], force=True, format="%(message)s")
20+
logger = logging.getLogger(__name__)
21+
logger.setLevel(logging.INFO)
22+
23+
# Configurar cliente de OpenAI según el entorno
24+
load_dotenv(override=True)
25+
API_HOST = os.getenv("API_HOST", "github")
26+
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")
27+
28+
async_credential = None
29+
if API_HOST == "azure":
30+
async_credential = DefaultAzureCredential()
31+
token_provider = get_bearer_token_provider(async_credential, "https://cognitiveservices.azure.com/.default")
32+
client = OpenAIChatClient(
33+
base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT']}/openai/v1/",
34+
api_key=token_provider,
35+
model_id=os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"],
36+
)
37+
elif API_HOST == "github":
38+
client = OpenAIChatClient(
39+
base_url="https://models.github.ai/inference",
40+
api_key=os.environ["GITHUB_TOKEN"],
41+
model_id=os.getenv("GITHUB_MODEL", "openai/gpt-5-mini"),
42+
)
43+
else:
44+
client = OpenAIChatClient(
45+
api_key=os.environ["OPENAI_API_KEY"], model_id=os.environ.get("OPENAI_MODEL", "gpt-5-mini")
46+
)
47+
48+
49+
@tool
50+
def get_weather(
51+
city: Annotated[str, Field(description="The city to get the weather for.")],
52+
) -> str:
53+
"""Devuelve datos del clima para una ciudad."""
54+
logger.info(f"Getting weather for {city}")
55+
conditions = ["soleado", "nublado", "lluvioso", "tormentoso"]
56+
return f"El clima en {city} está {conditions[random.randint(0, 3)]} con una máxima de {random.randint(10, 30)}°C."
57+
58+
59+
async def example_persistent_session() -> None:
60+
"""Una sesión con Redis persiste el historial de conversación incluso tras reinicios."""
61+
print("\n[bold]=== Sesión persistente en Redis ===[/bold]")
62+
63+
session_id = str(uuid.uuid4())
64+
65+
# Fase 1: Iniciar una conversación con un proveedor de historial en Redis
66+
print("[dim]--- Fase 1: Iniciando conversación ---[/dim]")
67+
redis_provider = RedisHistoryProvider(source_id="redis_chat", redis_url=REDIS_URL)
68+
69+
agent = Agent(
70+
client=client,
71+
instructions="Eres un agente de clima útil.",
72+
tools=[get_weather],
73+
context_providers=[redis_provider],
74+
)
75+
76+
session = agent.create_session(session_id=session_id)
77+
78+
print("[blue]Usuario:[/blue] ¿Cómo está el clima en Tokio?")
79+
response = await agent.run("¿Cómo está el clima en Tokio?", session=session)
80+
print(f"[green]Agente:[/green] {response.text}")
81+
82+
print("\n[blue]Usuario:[/blue] ¿Y París?")
83+
response = await agent.run("¿Y París?", session=session)
84+
print(f"[green]Agente:[/green] {response.text}")
85+
86+
# Fase 2: Simular un reinicio de la app — reconectar usando el mismo session_id en Redis
87+
print("\n[dim]--- Fase 2: Reanudando después del 'reinicio' ---[/dim]")
88+
redis_provider2 = RedisHistoryProvider(source_id="redis_chat", redis_url=REDIS_URL)
89+
90+
agent2 = Agent(
91+
client=client,
92+
instructions="Eres un agente de clima útil.",
93+
tools=[get_weather],
94+
context_providers=[redis_provider2],
95+
)
96+
97+
session2 = agent2.create_session(session_id=session_id)
98+
99+
print("[blue]Usuario:[/blue] ¿Cuál de las ciudades por las que pregunté tuvo mejor clima?")
100+
response = await agent2.run("¿Cuál de las ciudades por las que pregunté tuvo mejor clima?", session=session2)
101+
print(f"[green]Agente:[/green] {response.text}")
102+
print("[dim]Nota: El agente recordó la conversación de la Fase 1 gracias a la persistencia en Redis.[/dim]")
103+
104+
105+
async def main() -> None:
106+
"""Ejecuta los ejemplos de Redis para demostrar patrones de almacenamiento persistente."""
107+
# Verificar conectividad con Redis
108+
import redis as redis_client
109+
110+
r = redis_client.from_url(REDIS_URL)
111+
try:
112+
r.ping()
113+
except Exception as e:
114+
print(f"[red]No se puede conectar a Redis en {REDIS_URL}: {e}[/red]")
115+
print(
116+
"[red]Asegúrate de que Redis esté corriendo (por ejemplo, con el dev container"
117+
" o con 'docker run -p 6379:6379 redis:7-alpine').[/red]"
118+
)
119+
return
120+
finally:
121+
r.close()
122+
123+
print("[dim]Conexión a Redis verificada.[/dim]")
124+
125+
await example_persistent_session()
126+
127+
if async_credential:
128+
await async_credential.close()
129+
130+
131+
if __name__ == "__main__":
132+
asyncio.run(main())

0 commit comments

Comments
 (0)