Contexto sin base de datos: entrena tu agente con un Markdown

  1. .NET
  2. in 2 days
  3. 5 min read

Este es el episodio 5 de 6 del curso: le damos al agente el conocimiento real de la clínica dental sin base de datos, sin RAG y sin embeddings. Un archivo Markdown que cualquier dueño de negocio puede editar, y que el agente lee completo al arrancar.

El archivo business-info.md

El proyecto ya tenía este archivo vacío desde el episodio 2. Ahora lo llenamos con la información real del negocio:

# Clínica Dental Sonrisa
## Sobre nosotros
Somos una clínica dental en Quito, Ecuador, con más de 10 años
de experiencia. Nuestro enfoque es la atención personalizada
y de calidad para toda la familia.
## Servicios y precios
- Limpieza dental: 35 dólares (incluye revisión inicial sin costo)
- Blanqueamiento dental: 120 dólares
- Ortodoncia fija: desde 800 dólares
- Ortodoncia invisible (Invisalign): desde 1.500 dólares
- Extracción simple: 40 dólares
- Endodoncia (conducto): desde 150 dólares
- Implante dental: desde 600 dólares
## Equipo médico
- Dra. Valeria Moreno, martes y jueves
Especialista en odontología estética, 8 años de experiencia
- Dr. Carlos Vega, lunes, miércoles y viernes
Especialista en ortodoncia e implantes, 12 años de experiencia
## Horarios de atención
Lunes a viernes: 8:00 AM a 6:00 PM
Sábados y domingos: no atendemos
## Ubicación
Av. Naciones Unidas y Shyris, Edificio Plaza Mayor, Piso 3
Norte de Quito, a 5 minutos del CC Quicentro
## Formas de pago
- Efectivo
- Tarjeta de crédito y débito
- Transferencia bancaria
- Planes de financiamiento disponibles (consultar)
## Contacto
- Teléfono: 02-234-5678
- WhatsApp: 0998-765-432
- Email: info@clinicasonrisa.ec
## Configuración
- Moneda: dólares
- País: Ecuador

Servicios con precios, equipo médico, horarios, ubicación, formas de pago. Todo lo que un cliente real preguntaría. El dueño del negocio edita este archivo sin tocar una línea de código.

Copy to Output: el detalle que revienta al 80%

Antes del código, un ajuste de propiedades que si te lo saltas, revienta en el primer F5. Clic derecho sobre business-info.md en el Solution Explorer, Properties:

Build Action: Content
Copy to Output: Copy always

Sin esto, el archivo no se copia al directorio de ejecución y File.ReadAllTextAsync("business-info.md") lanza un FileNotFoundException en cuanto arranca el programa. Es la razón por la que el .csproj del proyecto incluye este bloque:

<ItemGroup>
<None Update="business-info.md">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

El código: leer el Markdown e inyectarlo en las instrucciones

Dos cambios respecto al episodio anterior. El primero, leer el archivo:

string businessInfo = await File.ReadAllTextAsync("business-info.md");

El segundo, inyectar ese contenido dentro de las instrucciones del agente en vez de escribir la descripción del negocio a mano:

AIAgent agent = new ChatClientAgent(
chatClient,
instructions: $"""
Eres un asistente virtual de la siguiente clínica dental.
Usa ÚNICAMENTE la información del negocio para responder.
Si no sabes algo, di que no tienes esa información.
Responde siempre en español, de forma amable y conciso.
La moneda, símbolo y país están definidos en la sección
"Configuración" del documento. Úsalos siempre al mencionar precios.
=== INFORMACIÓN DEL NEGOCIO ===
{businessInfo}
""",
name: "ClinicaDentalSonrisaBot");

No hay vector store, no hay paso de embeddings, no hay chunking. Todo el archivo entra completo dentro del system prompt. Funciona bien mientras el conocimiento del negocio quepa cómodo en una sola página; se convierte en el enfoque equivocado el día que ese archivo crezca a varios documentos o necesite filtrarse por sucursal. Ese día, la migración natural es agregar un paso de recuperación antes de esta línea, sin tocar el resto de la arquitectura del agente.

La instrucción “usa ÚNICAMENTE la información del negocio” es la que hace que el agente no invente. Se ve en la demo.

La demo: precios reales y una pregunta que el agente rechaza

🦷 Clínica Dental Sonrisa — Asistente Virtual
Tú: ¿Cuánto cuesta una limpieza?
Agente: Una limpieza dental tiene un costo de $35 e
incluye revisión inicial sin costo adicional.
Tú: ¿Tienen plan de pagos?
Agente: Sí, contamos con planes de financiamiento
disponibles. Te recomiendo consultarnos
directamente para más detalles.
Tú: ¿Abren los sábados?
Agente: Lo sentimos, no atendemos los sábados ni
domingos. Nuestro horario es de lunes a
viernes de 8:00 AM a 6:00 PM.
Tú: ¿Cuánto cuesta el encebollado con chifles?
Agente: Lo siento, no tengo esa información disponible.
Solo puedo ayudarte con consultas relacionadas
con los servicios de Clínica Dental Sonrisa.

Ese último intercambio es el más importante de los cuatro. El agente rechaza una pregunta fuera de contexto en lugar de inventar una respuesta. No alucina un precio para el encebollado; dice que no tiene esa información. Esa restricción, más que cualquier otra línea de código, es lo que hace que un asistente así sea confiable en producción.

Por qué esto es vendible

El dueño de la clínica edita el Markdown (cambia un precio, agrega un doctor) y el agente ya lo sabe, sin desplegar de nuevo y sin tocar código. El mismo agente, con un Markdown distinto, sirve para un restaurante con su menú o una ferretería con su catálogo. Lo único que cambia es el archivo.

Qué sigue

El agente ya entiende el negocio, pero todavía vive dentro de una consola en tu máquina. En el episodio 6 lo conectamos a Telegram: el cliente escribe por ahí, el agente lee el Markdown, Azure TTS responde con voz, y el bot queda accesible para cualquiera con la app instalada.

Si estás siguiendo el curso: llena tu propio business-info.md, configura Copy to Output antes de correr el proyecto, y prueba haciéndole al menos una pregunta que no esté en el archivo. Si el agente inventa una respuesta en vez de decir que no sabe, revisa la instrucción de sistema antes de seguir. El código completo está en el repositorio del proyecto.

Mira el video del episodio

Microsoft Agent Framework Google Gemini C# .NET 10 Agentes de IA