毎週月曜の朝、調達チームは同じ受信箱を開き、同じ山を見ます。サプライヤー契約です。マスターサービス契約、秘密保持契約(NDA)、発注書、変更契約——十数件から二十数件の新規文書が、それぞれ相手先の形式でPDFやWordファイルとして届きます。そのどれもが、あなたのチームが見慣れたテンプレートとはかけ離れた書式です。
そして、各契約は1週間が終わるまでに、次の一連の処理を通過しなければなりません。
- 誰かが契約を読み、重要条項を抜き出す——当事者は誰か、金額はいくらか、開始日はいつか、どう終了できるか
- 同じ条項をレビュー管理表に手入力する
- 契約を社内ポリシーと照合し、承認するか差し戻す
- 承認を通過した各ベンダーには、新しい契約書を作成する——標準テンプレートを開き、十数個のフィールドを置き換え、PDFに書き出す——ベンダーごとに、毎回
ほとんどの企業で、このワークフローは手作業で、反復的で、エラーが起きやすいものです。そして、これはまさに**AI文書エージェント(AI document agent)**が解決すべき仕事です。本記事ではその理由を説明し、.NETでエージェントを構築します。契約のバッチをレビューし、承認ルールを適用し、承認された各ベンダーに署名可能な契約書を生成します。
1. 手動ワークフローがなぜ負担になるのか
手動プロセスを構造だけ取り出すと、次のようになります。
PDF契約 → 1通ずつ読む → 重要条項をExcelに入力 → 手動承認 → テンプレートに手入力 → ベンダーごとにPDFを書き出す
これはすべての段階に人が介在するパイプラインであり、その形状こそがコストの原因です。
- 同じ文書を何度も読む。 レビュー、記録、ドラフト作成のたびに契約書を再度開きます。同じテキストを、同じ人が3回読むことになります。
- データを手でコピーする。 ベンダー名、契約額、支払条件がPDFからセル単位でスプレッドシートへ移ります。転記ミスが発生し、フィールドが抜け落ち、誰も気づきません。気づいたときには、間違った契約が外に出た後です。
-
承認されたベンダーごとに新しい契約が必要。 テンプレートを開き、十数個の
{{Placeholder}}フィールドを置き換え、PDFを書き出す——これをベンダーごとに繰り返します。法務や財務が気にする書式は、あなたが毎回同じように実行できるかにかかっています。 - 量が増えると計画が崩れる。 新しいサプライヤーパネル、四半期末の追い込み、監査——バックログは倍増し、チームはただ残業するだけになります。
これらの作業はどれも難しくはありません。ただ数が多く、形が一定なだけです。これはまさにソフトウェアが吸収すべき仕事です。
2. 読み、判断し、文書を書くエージェントというアイデア
1つのコンポーネントが3つのことをできれば、ワークフローは一気に縮みます。
- 読む(Understand)——文書を理解する。ベンダーがどんな書式で送ってきても、当事者、金額、日付、義務を抽出する。
- 判断する(Decide)——抽出した情報に、あなたの会社の承認ルールを適用する。
- 書く(Manipulate)——契約テンプレートと承認済みベンダーリストを受け取り、各ベンダーに1通、形式の整った契約書を生成する。
これが、AIチャットボット(Chatbot)(テキストを読んで返答するだけ)とAIエージェント(Agent)(文書を読み、行動し、新しい文書を成果物として生成する)の違いです。パイプラインは次のようになります。
文書 → AIレビュー → 構造化データ → 業務ルール → 承認済みベンダー → 契約生成
これまでファイル間でフィールドをコピーしていた人は、例外の承認と出力のレビューだけを担当します。中間のすべてが自動化されます。
3. .NETでSpire.Agent.Officeを使って実装する
.NETアプリケーションでは、このワークフローをSpire.Agent.Officeで実装できます。Word、Excel、PowerPoint、PDFの4形式に対して、1つのAI()プロセッサーを統一して公開する文書AIエージェントSDKです。設計はシンプルです。通常のSpire APIで文書を読み込み、エージェントを接続し、自然言語の指示を与えるだけ。あとはエージェントが処理します。
セットアップはNuGetパッケージとトークンだけです。
dotnet add package Spire.Agent.Office
Spire.Agent.OfficeはSpireTokenでAI機能を有効化します(公式サイトから無料版と商用版が入手可能)。.NET 10をサポートし、Windows、macOS、Linux、Dockerで動作します。
ステップ1 — エージェントを一度だけ設定する
4形式すべてで同じ設定を共有します。AIOptionsを作成し、トークンを設定し、WorkDirをセッションと生成ファイルの置き場所に指定します。
using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;
AIOptions agent = new AIOptions
{
SpireToken = spireToken, // Spire.Agent.Officeアカウントから取得
WorkDir = @"C:\legal-ops\work",
TimeoutMs = 300_000
};
WorkDirは重要です。エージェントのセッションフォルダがここに置かれるためです——その中身は後ほど見ていきます。
ステップ2 — 受信箱のすべての契約をレビューする
中核となる呼び出しはExecuteInstruction(document, instruction, outputPath, attachments)です。文書オブジェクトを渡し、やりたいことを平易な言葉で説明すると、AIResultが返ります。ここでは、今週届いた各PDFを読み込み、構造化されたレビューブリーフを依頼します。
using Spire.Pdf;
string reviewInstruction =
"このサプライヤー契約をレビューし、Markdownのブリーフを作成してください。" +
"当事者、発効日、契約額、支払条件、責任上限、解約通知期間を1行の表にまとめ、" +
"さらに標準的なサプライヤー契約として不自然な条項を箇条書きにしてください。";
foreach (string file in Directory.GetFiles(inboxPath, "*.pdf"))
{
string briefPath = Path.Combine(
briefsPath, Path.GetFileNameWithoutExtension(file) + ".md");
using (PdfDocument agreement = new PdfDocument())
{
agreement.LoadFromFile(file);
AIResult result = agreement.AI(agent).ExecuteInstruction(
agreement, reviewInstruction, briefPath, Array.Empty<string>());
if (result is null || !result.Success)
throw new InvalidOperationException(
$"レビューに失敗しました {Path.GetFileName(file)}:{result?.ErrorMessage}");
}
}
エージェントはPDFをネイティブ形式のまま読み取ります——テキスト抽出の前処理も、レイアウトごとのルールも不要です。数分のエージェント実行時間で、1週間分の「読む+コピーする」作業が置き換わります。
ステップ3 — 承認判断は業務ルールに任せる
このステップは多くの人が飛ばしますが、AIワークフローを「説明責任を果たせるもの」にする要です。どのベンダーを承認するかという判断は、言語モデルに任せるべきではありません。決定的で監査可能なコードに置くべきです。
// エージェントが抽出し、あなたのコードが判断する。
var approved = new List<ReviewResult>();
foreach (ReviewResult r in ParseBriefs(briefsPath)) // ステップ2から
{
bool passes = r.PartyCount >= 2
&& r.LiabilityCap >= 1_000_000m // 当社の下限
&& r.TerminationNotice <= 60; // 日
if (passes) approved.Add(r);
}
WriteVendorList(@"C:\legal-ops\data\approved-vendors.xlsx", approved);
(ParseBriefsとWriteVendorListは、既存のトラッカー読み取り・スプレッドシート出力の方法で構いません——エージェントに抽出結果を.xlsx、.json、.csvで直接書き出させることもできます。重要なのは判断がどこにあるかです。コードに置けば、レビューでき、バージョン管理でき、監査で引用できます。)
承認されたベンダーだけが最後のステップに進みます。
ステップ4 — 承認されたベンダーごとに契約書を1通生成する
ここでエージェントが行うのは、決定的なSDKなら数十行のReplace呼び出しで済ませる作業です。1つのテンプレートと承認リストから、各行に1通の契約書を生成します。
using Spire.Doc;
string[] attachments = { @"C:\legal-ops\data\approved-vendors.xlsx" };
using (Document contract = new Document())
{
contract.LoadFromFile(@"C:\legal-ops\templates\supplier-contract.docx");
AIResult result = contract.AI(agent).ExecuteInstruction(
contract,
"承認された各ベンダーに購入契約書を1通発行してください。" +
"approved-vendors.xlsxを1行ずつ読み、このテンプレートの{{Placeholder}}フィールドを" +
"各ベンダーのデータで埋め、テンプレートのレイアウトとスタイルを維持し、" +
"各契約書を作業ディレクトリの独立したPDFとして保存してください。",
null, // ベンダーごとに1ファイル、エージェントが書き出す
attachments);
if (result is null || !result.Success)
throw new InvalidOperationException(
$"契約書の生成に失敗しました:{result?.ErrorMessage}");
}
テンプレートはプレースホルダーを担い、スプレッドシートはデータを担い、1つの指示がすべての契約書を駆動します。条項番号、表、フォントは、出力が決定的な文書エンジンによって生成されるため維持されます——言語モデルがファイル形式を即興で作るわけではありません。outputPathをnullにした場合、単一の返却ファイルはなくなり、エージェントはベンダーごとに1通のPDFをWorkDir配下のセッションフォルダに書き出します。
4. 仕組み:エージェントはディスク上に何を残すのか
ここが私が最も面白いと思う部分であり、この種のエージェントが法務ワークフローで信頼に足る理由です。ExecuteInstructionを呼ぶたびに、エージェントは**セッション(session)**を実行し、すべてのセッションはWorkDir配下にファイルとして残されます。
C:\legal-ops\work\
└─ .office_use_tmp\
└─ Word\
└─ 0812093540_c6825d69dd\ ← ExecuteInstruction呼び出しごとに1セッション
├─ process.csx ← エージェントが生成したC#スクリプト
├─ input.docx ← 処理対象の契約テンプレート
├─ approved-vendors.xlsx ← 読み込んだ承認済みベンダーリスト
├─ output_Brightpath_Analytics_Ltd.pdf
├─ output_Evercrest_Digital_Solutions_Inc.pdf
└─ output_Novalune_Systems_LLC.pdf
セッションフォルダはフラットで自己完結的です。入力文書、生成スクリプト、承認済みベンダーごとの出力PDF(ベンダー名で命名)が同じ場所に並びます。セッションIDは「タイムスタンプ+短いハッシュ」なので、バッチ実行でもフォルダが衝突しません。
エージェントはファイルを魔法のように変更するわけではありません。タスクを計画し、Spire文書APIを駆動する本物のC#スクリプト(process.csx)を書き、.NETスクリプトランタイムで実行し、入力と出力をセッションフォルダに配置します。スクリプトは自己完結的です。先頭の#r "nuget: ..."ディレクティブで必要なSpireパッケージを自ら取得し、宣言したバージョンで実行するため、アプリケーションが読み込んでいるパッケージに依存しません。
この点は具体化する価値があります。process.csxは、.NET開発者が手書きするコードとまったく同じものだからです。
// process.csx — エージェントが生成したスクリプト(省略版)
var workDir = Args[0];
using (var wb = new Workbook())
{
wb.LoadFromFile(Path.Combine(workDir, "approved-vendors.xlsx"));
// ... 各行のベンダーデータを vendors に読み込む
}
foreach (var v in vendors)
{
var doc = new Document();
doc.LoadFromFile(Path.Combine(workDir, "input.docx"));
doc.Replace("{{Vendor Name}}", v["Vendor Name"]);
doc.Replace("{{Payment Terms}}", v["Payment Terms"]);
doc.Replace("{{Contract Term}}", v["Contract Term"]);
var fileName = "output_" + v["Vendor Name"].Replace(' ', '_') + ".pdf";
doc.SaveToFile(Path.Combine(workDir, fileName), Spire.Doc.FileFormat.PDF);
doc.Dispose();
}
エージェントは承認ワークブックを読み、行ごとにテンプレートを読み込み、プレースホルダーを1つずつ置き換え、ベンダーごとにPDFを書き出し——そしてスクリプトをディスクに残して、あなたが読めるようにしました。これが決定的な文書レイヤーの役割です。モデルが何を埋めるかを決定し、スクリプトはそれを実行するごく普通のSpire APIコードです。
これには3つの実用的な帰結があります。
-
検証可能。
process.csxを開けば、テンプレートに対して実行された操作——どのプレースホルダーを置き換えたか、PDFをどう書き出したか——をそのまま読めます。盲目的に信じるブラックボックスはありません。 - 監査可能。 セッションフォルダは完全な記録です。入力文書、スクリプト、出力文書が一揃いです。契約にとって、この紙の証跡は「擁護できる自動化」と「祈るしかない自動化」の分かれ目です。
-
出力は本物の文書。 スクリプトが決定的なエンジンを駆動するため、結果は整形された
.docxまたは.pdfであり、テキストの塊ではありません。モデルが何を行うかを決め、エンジンがファイルがどう構築されるかを保証します。
これが、文書エージェントが「PDFを要約するAI」と違う理由です。再現可能で検証可能な痕跡を残し、署名できるファイルを手元に返してくれます。
5. LLM単体ではなくエージェントを使う理由
LLM APIにアクセスできるなら、「プロンプトで契約を生成する」という形で文書レイヤーを飛ばしたくなるでしょう。しかし契約のシナリオでは、この方法は3つの点で失敗します。
-
LLMはOfficeファイルを確実に読み書きできない。 LLMが見るのはテキストであり、
.docxや.pdfの構造ではありません。Wordテンプレートを読み、表を保ち、有効なPDFを生成するには、独自の抽出・再構築パイプラインを組む必要があります。 - 書式こそが成果物。 契約テンプレートには条項番号、表、フォントが含まれ、法務と財務がこれを重視します。素のLLMはテキストを返すだけで、失われた書式は受け取り側が最も気にする部分です。
- オーケストレーション全体を自分で保守する。 プロンプト設計、パース、ファイルI/O、エラー処理がすべてあなたのコードになり、さらにLLMの非決定性にも耐える必要があります。
エージェントは、モデルの言語理解と決定的な文書レイヤーを組み合わせます。モデルは何を抽出し埋めるかを決定し、文書レイヤーはファイルそのものを保証します。それが「デモ」と「チームが本番に乗せられるワークフロー」の違いであり——先ほど見たように、その違いは文字どおりディスクに書かれています。
6. このパターンは契約だけにとどまらない
このパイプライン——理解 → 判断 → 操作 → バッチ——には契約固有の要素は何もありません。同じエージェントに、違う指示と違うテンプレートを与えれば、チームが次に自動化したい仕事が処理できます。
- 履歴書のスクリーニング:PDF/DOCXの履歴書フォルダから候補者情報を抽出し、採用ルールを適用し、オファーレターを生成する。
- 請求書処理:PDFから請求番号、ベンダー、金額、税額を抽出し、例外をフラグし、支払いレポートを生成する。
- RFP応答:要件文書を読み、自社の能力ライブラリと照合し、提案書を作成する。
- ベンダー見積もり比較:PDFとExcelの見積もりを正規化し、行ごとに比較し、購買分析レポートを生成する。
どれも同じアーキテクチャです。指示が1つ入り、本物の文書が1つ出て、ディスク上には何が起きたかを示すセッションフォルダが残ります。
7. まとめ
契約レビューと生成は、AI文書エージェントから最も早く価値を得られる場所の1つです。PDFの束が入り、コードが決定する承認リストを経て、承認された各ベンダーに署名可能な契約書が1通ずつ出る——それぞれのファイルの背後には、監査できるprocess.csxセッションがあります。
今回構築したワークフローは文書あたり数秒で動作し、法務アナリストの1週間分の「読む+コピーする」作業を置き換えます。そして、AIに任せるべきでない2つのことをループの外に確実に残します。二択の承認判断はコードに、最終文書は本物の整形済みファイルに。
試してみたくなったら、Spire.Agent.Office統合入門チュートリアルが統合を案内し、製品概要が公開する4つのエージェント(Word、Excel、PowerPoint、PDF)を紹介しています。上記の例が統合面のすべてです——残りは指示だけです。
