Pídele a un agente de IA que “escriba el acuerdo de servicio para Contoso” y lo hará, con sus propias palabras, con sus propios encabezados y con un total que habrá calculado mentalmente. Esa es la división de trabajo equivocada. Con GroupDocs.Assembly.Mcp ejecutándose localmente (dnx GroupDocs.Assembly.Mcp --yes), Claude Desktop, Cursor o Copilot le preguntan a tu plantilla de Word qué campos necesita, los rellenan a partir de tus notas y el motor genera el contrato, la tabla y los cálculos incluidos, sin que el modelo toque el diseño:

Haz el acuerdo de servicio para este pedido usando contract-template.docx y guárdalo como PDF: Contoso Pharma, Keizersgracht 210 Ámsterdam, contacto Dra. Lena Brandt; 12 meses de hosting gestionado a 4.800 EUR, 12 meses de soporte a 1.200 EUR, un taller de incorporación a 3.500 EUR; 5 por ciento de descuento.

La versión paso a paso con configuración y solución de problemas está en la documentación: Cómo generar documentos a partir de plantillas con agentes de IA usando MCP.

¿Por qué el modelo no debería redactar el documento?

Porque un documento generado falla de maneras que son difíciles de detectar. El diseño se desvía del aprobado legalmente. Una cláusula se parafrasea en algo que suena bien pero significa otra cosa. Un total se obtiene mediante predicción de siguiente token en lugar de multiplicación. Y cada ejecución es un poco diferente, de modo que la revisión del mes pasado no te dice nada sobre el contrato de este mes.

Una plantilla invierte eso. El área legal posee contract-template.docx, con sus encabezados, su bloque de firma y sus etiquetas <<[customer.Name]>>. El trabajo del modelo se reduce a la parte en la que es bueno: leer un correo electrónico o un conjunto de notas y convertirlo en valores estructurados. El motor hace el resto, de la misma manera cada vez.

¿Cómo sabe el agente qué rellenar?

Le pregunta a la plantilla. get_template_fields lee las etiquetas sin ejecutar el motor y devuelve los nombres que usa la plantilla, cada campo que lee y un esqueleto JSON para rellenar. Esto es lo que el servidor devolvió para nuestra plantilla de contrato:

-> get_template_fields {"template":{"filePath":"contract-template.docx"}}
<- { "tagCount": 17,
     "dataSourceNames": [ "contract", "customer", "items" ],
     "dataSkeleton": {
       "contract": { "Number": "", "Date": "", "Discount": "" },
       "customer": { "Name": "", "Address": "", "Contact": "",
                     "Email": "" },
       "items": [ { "Title": "", "Quantity": 0, "UnitPrice": 0 } ] } }

Ese esqueleto es el contrato entre el modelo y el documento. El agente lo rellena a partir del texto del pedido y lo devuelve como dataJson.

¿Qué ocurre cuando el agente olvida un campo?

Se le indica, de forma precisa. En nuestra prueba el primer intento del agente omitió la dirección de correo electrónico del cliente. El servidor lo rechazó y señaló la omisión:

-> assemble_document {"template":{...},"dataJson":"{... no Email ...}"}
<- Document assembly failed for 'contract-template.docx': ...
   Can not get the value of member 'Email' on type ''. The template
   reads 'Email', which the data does not have. Check the spelling
   (names are case-sensitive) with get_template_fields and add it to
   the data. ... pass allowMissingMembers=true to output nothing for
   missing members and empty lists.

Un modelo que escribe texto libre habría dejado la línea en silencio. Aquí el agente puede pedirte la dirección, o decidir contigo que el campo puede quedar vacío.

Todo el intercambio

user            agent                       Assembly MCP server
 | "Make the contract for this order: ..."                      |
 |-------------->|                                              |
 |               |-- get_template_fields {"template":          |
 |               |     "contract-template.docx"} ------------->|
 |               |<- dataSkeleton: contract, customer, items --|
 |               |   (fills the skeleton from the order text)  |
 |               |-- assemble_document {"dataJson":"{...}",    |
 |               |     "format":"pdf"} ----------------------->|
 |               |<- Saved to: .../contract-template_          |
 |               |   assembled.pdf ----------------------------|
 |<- "Contract ready: 3 items, total 75500 EUR, 5% discount."  |
   layout, table and arithmetic come from the template

Con el correo electrónico añadido, la segunda llamada tuvo éxito:

-> assemble_document {"template":{"filePath":"contract-template.docx"},
     "dataJson":"{...}","format":"pdf"}
<- Assembled 'contract-template.docx' with inline JSON (JSON object)
   as PDF
   Saved to: .../contract-template_assembled.pdf

El documento contiene una tabla de honorarios de tres filas construida por un <<foreach>> en la fila de la tabla, importes calculados por la plantilla (<<[item.Quantity * item.UnitPrice]>>), un total de 75 500 EUR a partir de items.Sum(...) y la línea “Se aplica un descuento del 5 por ciento.”, que solo existe porque una etiqueta <<if>> encontró un descuento en los datos. El modelo no calculó nada de eso.

¿Es esto mejor que un servicio de plantillas alojado?

Es un intercambio diferente. Los servicios de plantillas alojados toman tu plantilla y datos a través de HTTPS, renderizan en su nube y cobran por documento o por crédito. Aquí la plantilla, los datos y la salida permanecen en una carpeta de tu máquina; el motor es GroupDocs.Assembly ejecutándose en proceso, y nada escucha en un puerto. Lo que viaja a tu proveedor de modelo es el texto del pedido que pegas y el esqueleto que el agente rellena, no el contrato renderizado. La arquitectura está descrita en la publicación familiar sobre procesamiento de documentos de IA on‑premise.

Límites honestos

  • Modo de evaluación: cada documento generado comienza con la línea “Evaluation Only. Created with GroupDocs.Assembly 26.7…”, los libros de trabajo guardados ganan una hoja extra y las plantillas de correo electrónico conservan solo su cuerpo en texto plano. Un archivo de licencia o claves con medición eliminan los tres.
  • La sintaxis de la plantilla es <<[name]>>. Los marcadores {{name}} se dejan como texto; get_template_fields lo indica.
  • Las plantillas son entrada confiable: las etiquetas de imagen y documento cargan cualquier ruta o URL que devuelva su expresión. Monta una carpeta para el servidor.
  • Fechas: escríbelas como 2026-11-12T00:00:00 y formatealas en la plantilla (<<[contract.Date]:"d MMMM yyyy">>). Una fecha solo "2026-11-12" se imprimió como 12 noviembre en una máquina UTC+2 en nuestra prueba.
  • El agente es la fuente de datos. Pídele que enumere los valores que extrajo antes de renderizar y revíselos.

Preguntas frecuentes

¿Puede un agente de IA rellenar mi plantilla de Word sin subirla?
Sí. El servidor se ejecuta localmente sobre stdio y lee la plantilla de la carpeta que configures; la salida se escribe junto a ella.

¿En qué formatos puede estar la plantilla?
Word, Excel, PowerPoint, Markdown, HTML, texto y plantillas de correo electrónico; cada una puede guardarse en su propio formato o en PDF y otros. get_supported_formats las enumera por plantilla.

¿Qué pasa si la plantilla la mantiene otra persona?
Ese es el objetivo. Quien sea el propietario de la plantilla cambia cláusulas y diseño; el agente sigue rellenando el mismo esqueleto, y get_template_fields le muestra cualquier campo nuevo la próxima vez que pregunte.

Profundiza