ברכות קבלה לארבעים לקוחות חדשים, תעודה לכל משתתף, חשבונית לכל הזמנה: אותו מסמך, רשומה שונה בכל פעם. עם GroupDocs.Assembly.Mcp הפועל מקומית (dnx GroupDocs.Assembly.Mcp --yes), Claude Desktop, Cursor או Copilot מבצעים זאת בקריאה אחת לכלי, assemble_per_record, שממלא את תבנית ה‑Word שלך פעם אחת לכל אלמנט במערך JSON, שומר כל תוצאה כ‑PDF משלה בשם שדה שתבחר, ומדווח על הרשומות שנכשלו במקום לעצור ברשומה הראשונה:
צור PDF של מכתב קבלה לכל לקוח ב‑customers.json באמצעות welcome-letter.docx, וקרא לכל קובץ בשם הלקוח.
הגרסה המפורטת שלב‑אחר‑שלב עם תצורה ופתרון בעיות נמצאת בתיעוד: How to generate one document per record (mail merge) with an AI agent .
למה לא לתת לסוכן לבצע לולאה?
הסוכן יכול, ולחמישה רשומות זה בסדר. אבל לולאה של ארבעים קריאות לכלי היא ארבעים סיכויים שהסוכן יאבד ספירה, ידלג על רשומה כאשר ההקשר מתארך, או “בצורה מועילה” ישנה ניסוח של מכתב אחד. כלי לכל רשומה מעביר את הלולאה לשרת: קריאה אחת, תבנית אחת, מעבר אחד על המערך, ודוח שמציין בדיוק כמה קבצים נכתבו ואילו רשומות לא הושלמו. תפקיד הסוכן הוא לבחור את התבנית, קובץ הנתונים ואת שדה השם, ולאחר מכן לקרוא את הדוח חזרה אליך.
מה הסוכן בודק ראשון?
שניים: איך נראים הנתונים, ומה קוראת התבנית. בבדיקה שלנו, חמישה לקוחות ב‑customers.json ומכתב קבלה בעמוד אחד:
-> get_document_info {"file":{"filePath":"customers.json"}}
<- { "dataKind": "json",
"data": { "root": "array", "length": 5, "keys": null } }
-> get_template_fields {"template":{"filePath":"welcome-letter.docx"}}
<- { "dataSourceNames": [ "customer" ],
"fields": [ "customer.Contact", "customer.Plan", "customer.Name",
"customer.Manager", "customer.FirstInvoice" ] }
התבנית קוראת רשומה אחת בשם customer; השרת מגלה זאת בעצמו, ולכן הסוכן אינו צריך להעביר dataSourceName.
קריאה אחת, חמש רשומות, כשל אחד
-> assemble_per_record {"template":{"filePath":"welcome-letter.docx"},
"data":{"filePath":"customers.json"},"fileNameField":"Name",
"format":"pdf"}
<- Assembled 4 of 5 document(s) from 'welcome-letter.docx' with
'customers.json', one per record (each record as 'customer'), as PDF.
Saved to:
.../Contoso Pharma.pdf
.../Fabrikam Logistics.pdf
.../Tailspin Toys.pdf
.../Litware Labs.pdf
1 record(s) failed:
record 4: InvalidOperationException: ... Can not get the value of
member 'FirstInvoice' on type 'System.Data.DataRow'. The template
reads 'FirstInvoice', which the data does not have. ...
רשומה 4, Wingtip Travel, לא הייתה לה תאריך חשבונית ראשון בנתונים. ארבעת המכתבים האחרים נכתבו, כל אחד בשם הלקוח, והכשל חזר עם מספר הרשומה והשדה שהחסר. סוכן מדווח זאת כ‑“ארבעה מכתבים הושלמו; ל‑Wingtip Travel אין תאריך חשבונית ראשון, האם ברצונך להשאיר את השורה ריקה או לחכות לתאריך?”. זו השיחה שאתה רוצה, במקום ארבעים קבצים וללא מושג איזו שגויה.
איך פועל הפיזור
customers.json [ {Name:"Contoso Pharma",...}, {Name:"Fabrikam ..."},
... 5 records ]
|
assemble_per_record {"template":{"filePath":"welcome-letter.docx"},
"data":{"filePath":"customers.json"},
"fileNameField":"Name","format":"pdf"}
|
+--> Contoso Pharma.pdf
+--> Fabrikam Logistics.pdf ... 2 more
'--> "4 of 5 ... 1 record(s) failed: record 4 ..."
שלושה פרמטרים עושים את העבודה. fileNameField נותן שם לכל פלט לפי שדה ברשומה, customer.Name או מספר חשבונית; ללא זה, הקבצים מקבלים מספר רציף. recordsPath מצביע על המערך כאשר ה‑JSON הוא אובייקט שמכיל אחד, כגון "customers" או "batch.items". ו‑maxDocuments הוא הבלם.
מה עוצר אצווה רצה?
maxDocuments, שמוגדר כברירת מחדל ל‑100 ויכול להגיע עד 1000. לפני כתיבה של כל דבר, השרת סופר את הרשומות; אם יש יותר מהמגבלה, הוא מסרב. קבענו אותו ל‑3 מול חמשת הלקוחות שלנו:
-> assemble_per_record {..., "maxDocuments":3}
<- Per-record assembly failed for 'welcome-letter.docx': there are 5
records, more than maxDocuments=3. Raise 'maxDocuments' (up to 1000)
or pass fewer records.
שום דבר לא נכתב. עבור שליחת דואר שמיועדת לאנשים אמיתיים, זהו ברירת המחדל הנכונה: שאלה שמופיעה במקרה שהמערכת מציינת את כל ייצוא ה‑CRM מחזירה שאלה, ולא עשרת אלפי PDF‑ים.
הנתונים שלי הם גיליון אלקטרוני, לא JSON
הפקודה ליצירת מסמך לכל רשומה קוראת רק JSON: מערך של אובייקטים, או אובייקט שמחזיק אחד. כאשר הרשימה נמצאת בקובץ CSV או בגיליון, הסוכן ממיר את השורות ל‑JSON תחילה, מה שסוכנים עושים היטב, וכותב את הקובץ לתיקיית האחסון. אם מה שאתה רוצה הוא מסמך אחד שמפרט כל שורה, רשימת מחירים או רישום, זה assemble_document עם <<foreach>> בתבנית, והוא קורא CSV וגיליונות אלקטרוניים ישירות.
מגבלות כנות
- יצירת מסמך לכל רשומה קוראת רק JSON; נתוני CSV וגיליון צריכים המרה תחילה.
- מצב הערכה: כל קובץ שנוצר מתחיל ב‑“Evaluation Only. Created with GroupDocs.Assembly 26.7…”, ותבניות דוא"ל משמרות רק את גוף הטקסט הפשוט שלהן. יש לרשום את השרת לפני שליחת דואר אמיתית.
- שדה חסר גורם לכשל של אותה רשומה.
allowMissingMembers: trueכותב אותה עם השורה ריקה במקום; החלט איזה אתה רוצה. - תאריכים: כתוב אותם כ‑
2026-12-01T00:00:00ועצב אותם בתבנית, כפי שהמכתב שלנו עושה עם<<[customer.FirstInvoice]:"d MMMM yyyy">>. מחרוזת תאריך בלבד הוזזה ביום אחד במכונה עם UTC+2 בבדיקה שלנו. - השרת כותב קבצים; הוא אינו שולח אותם. המשלוח הוא שלב נפרד.
שאלות נפוצות
האם אפשר לבצע מיזוג דואר עם Claude בלי להעלות את רשימת הלקוחות?
כן. השרת פועל מקומית וקורא customers.json מתיקיית האחסון שלך; ה‑PDF‑ים שנוצרו נכתבים שם גם הם.
איך נקראים קבצי הפלט?
לפי שדה הרשומה שאתה מעביר כ‑fileNameField, כאן שם הלקוח, ולכן Contoso Pharma.pdf. ללא זה, מספר רציף.
האם כל מסמך יכול להיות דוא"ל במקום PDF?
כן: השתמש בתבנית EML או MSG, או העבר format: "eml". במצב הערכה גוף ה‑HTML של הדוא"ל מוחלף בשורת ההערכה, ולכן יש לבדוק פלט דוא"ל עם רישיון.
צלילה עמוקה יותר
- תיעוד, מדריך קנוני: How to generate one document per record (mail merge) with an AI agent
- מרכז תיעוד: GroupDocs.Assembly MCP Server
- התחלה כאן: Let the model fill in the data, not write the document
- קשור: What does this template need? Ask it.
- קשור: The chart comes from the template, the numbers come from the data
- קשור: Your repo already has the data; let the agent make the PDF
- מודל פריסה וביטחון: 3 architectures for AI document processing, and the one that keeps files inside your network
- שאלות: GroupDocs Assembly forum
- מקור: GroupDocs.Assembly.Mcp on GitHub