装置トラブル対応エージェント — ツールの説明と仕様(図解)

製造現場の装置トラブルに、AIが設備台帳・マニュアル・保全記録を自分で調べて答えるエージェントの、仕組みと設計の考え方をまとめた資料です。データはすべて架空で、実在の装置・会社とは関係ありません。画面の動きは 画面のモック で見られます。コードは公開していません。使ってみたい・自分の現場に合わせたい、というご相談は、このページをご覧になったサービス(クラウドソーシングなど)のメッセージ機能からお願いします。ほかの作品は作品集にあります。

1. 30秒で説明する

製造現場の担当者が「ライン3の充填機でE-12が出た」と聞くと、AIが設備台帳・マニュアル・保全記録を自分で調べて、根拠つきで対処を答えるエージェントを、Claude API の Tool Use で作りました。

ツールは4つで、名前・説明・入力の形を自分で定義しています。AIがツールを呼んだら実行して結果を返すループも自分で実装し、上限10回で止まるようにしました。データを書き換える保全依頼だけは、人が承認してから登録します。どのツールをどの順で呼んだかは、ログで後から追えます。

例えるなら:新人の保全担当(AI)に、使い方のラベルを貼った道具を4つ渡し、伝令係(ループ)が道具を実際に動かして結果を届ける。書類の提出だけは上司の判子(人の承認)が要る。

2. 全体の仕組み

登場人物は5つ。AI(Claude)は「どの道具を使うか」を判断するだけで、道具を実際に動かすのは自分で書いたプログラム(ループ)です。

担当者 質問する 画面 app.py 質問 回答 ループ(伝令係) agent.py 最大10周まで繰り返す Claude(AI) どの道具を使うか判断 質問・道具の説明書 ・道具の結果 「この道具で  調べて」 または 回答 道具箱 tools.py get_equipment 設備台帳を調べる search_manual マニュアルを探す search_maintenance_log 保全記録を探す create_work_request 保全依頼を登録する(書き換え) すぐ実行 (読むだけ) 人の承認 承認ボタン/登録しない いったん止まる OKなら
図1:読むだけの3つの道具は、AIが選んだらすぐ実行する。データを書き換える保全依頼だけは、人の承認を通ってから実行する。AIは道具を直接さわらない。

3. 実際の動き(ライン3の充填機でE-12)

時間は上から下へ流れます。AIとの往復(②⑤⑧)が3回 = ループが3周。⑥ではAIが2つの道具を同時に頼み、ループは2つの結果を1通にまとめて返しています。

担当者 ループ Claude(AI) 道具・データ ①「ライン3の充填機でE-12」 ② 質問+道具の説明書(1周目) ③ 設備台帳で「ライン3 充填機」を ④ get_equipment を実行 EQ-003・型番 FL-200 ⑤ 結果を返す(2周目) ⑥ マニュアルと保全記録を同時に ⑦ 2つとも実行 5.3章「洗浄手順」/ML-0007「Oリング交換」 ⑧ 2つの結果を1通で(3周目) ⑨ 回答(もう道具は要らない) ⑩ 根拠つきの回答 「まず5.3章で洗浄、再発ならOリング交換」
図2:青い矢印がAIへの問い合わせ(=ループ1周)。③⑥⑨はAIの返事で、③⑥は「道具を使いたい」(tool_use)、⑨は「答え終わった」(end_turn)。

ポイント:最初に設備台帳で設備IDと型番を確定してから、型番でマニュアル、設備IDで保全記録を引く。同じ FL-200 がライン1にもあるので、ここを飛ばすと別の装置の記録が混ざる(サンプルデータの「引っかけ」)。

4. 4つの道具(ツールの仕様)

「AIへの説明文」は、ツールの定義にそのまま書いてある文章の要約です。AIはこの説明文を読んで、いつ・どの道具を使うかを決めます。

設備台帳を調べる承認なし

get_equipment
例え
設備の名簿を引く
AIへの説明文
装置名・ライン名・設備IDから台帳を調べる。質問に装置が出てきたら最初に使うこと。見つからなければ空の一覧を返す。
入力
query:例「ライン3 充填機」。空白で区切ると、すべての語を含む設備を探す
返すもの
設備ID・装置名・型番・ライン・設置場所・担当者(最大5件)
工夫
全角・半角の違いを吸収(「ライン3」でも見つかる)
なぜ:マニュアルは型番ごと、保全記録は設備IDごとに引くので、最初に両方を確定させる。

マニュアルを探す承認なし

search_manual
例え
その機種の取扱説明書の索引を引く
AIへの説明文
型番の取扱説明書から、エラーコードや症状に関係する箇所を探す。対処を答えるときは必ずこのツールで根拠を確かめること。
入力
model:型番「FL-200」/keywords:「E-12 ノズル」
返すもの
マニュアル名・章の見出し・本文(関係の強い順に最大3件)
探し方
章ごとに分け、キーワードが出てくる回数で並べる。型番が一致するマニュアルだけを探す
なぜ:型番で絞ると、ほかの装置のマニュアルが混ざらない。検索は単純にした(中身だけRAGに差し替えられる)。

保全記録を探す承認なし

search_maintenance_log
例え
その設備のカルテ(修理の履歴)を見る
AIへの説明文
同じ装置・同じエラーの対応履歴を探す。原因や、実際に効いた対処を知りたいときに使う。
入力
equipment_id:「EQ-003」/keywords:「E-12」
返すもの
記録ID・日付・エラーコード・症状・原因・対処・作業者(新しい順に最大5件)
なぜ:マニュアルは「一般的な対処」、保全記録は「この装置で実際に効いた対処」。両方そろうと答えの説得力が上がる。

保全依頼を登録する人の承認が必要

create_work_request
例え
修理の依頼書を出す(上司の判子が要る)
AIへの説明文
部品の交換など、現場で直せない対応が必要なときだけ使う。登録の前に必ず人の承認を求める。
入力
equipment_id/title(件名)/detail(内容と根拠)/priority(「高」「中」「低」の3つから選ぶ)
返すもの
承認:registered と依頼番号(WR-0001…)/登録しない:rejected_by_user
チェック
台帳に無い設備IDなら登録せず、理由をAIに返す
なぜ:読むだけの道具は自由に使わせ、データを書き換える道具だけ人の承認を挟む。AIの判断ミスが現場に直接届かないように。

5. 「ツールの定義」とは

AIに渡す「道具のラベル」です。1つの道具につき3つを書きます。AIはコードの中身を見られないので、このラベルだけを頼りに道具を選びます。

項目何を書くか保全依頼の例
名前(name)道具の名前create_work_request
説明(description)何をする道具か、いつ使うか・いつ使わないか。AIへの指示書のつもりで書く現場で直せない対応が必要なときだけ使う。登録の前に必ず人の承認を求める
入力の形(input_schema)記入欄の項目・型・選択肢設備ID・件名・内容・優先度(高/中/低のどれか)

strict(厳密モード)を付けた

記入欄が決まった申請書のようなもの。AIは決められた項目・型・選択肢どおりにしか書けない(優先度に「至急」とは書けない)。全部のツールに付けている。

使う順番はプロンプトで伝えた

このモデル(claude-opus-5-5)では「必ずこの道具を使え」と強制する設定(tool_choice)がエラーになる。だから「まず設備台帳で確かめて」とシステムプロンプトに書いて誘導している。

6. ループ(自分で書いた制御)

ループは「AIに聞く → AIの返事を見て次の行動を決める」の繰り返しです。AIの返事(stop_reason)によって、行き先は4つに分かれます。

AIに聞く 1周ごとに回数+1 AIの 返事は? 道具を実行し、結果を 1通にまとめて返す 道具を使いたい tool_use 次の周へ 完了:回答を表示 done 答え終わった end_turn 停止:理由を表示 stopped 10周を超えた/打ち切り/APIエラー 承認待ち:しおりを挟む needs_approval 保全依頼を使いたい ボタンが押されたら、しおりのところから続ける
図3:ループの行き先は4つ。止まらなくなるのを防ぐため、1つの質問でAIに聞くのは最大10回(config.MAX_TURNS)。
決まりごと(APIのルール)なぜ守るか
AIの返事は、中身を間引かずにそのまま会話の履歴に足すAIの考えたこと(思考のブロック)を削ると、次の判断がずれたりエラーになったりする
1回の返事で道具が2つ以上頼まれたら、結果は1通にまとめて返すAPIの決まり。分けて返すと、AIが同時に頼まなくなっていく
道具の結果を返していない間は、次の質問を送らない頼まれた道具の結果が抜けた履歴を送ると、APIエラーになる。だから承認待ちの間は入力欄を使えなくした

7. 人の承認(ガードレール)

画面(Streamlit)は、ボタンを押すたびにプログラムを最初から実行し直すしくみです。ループの途中で「ボタンが押されるまで待つ」ことができません。そこで、本にしおりを挟んで閉じるように止めて、押されたら続きから読む形にしました。

  1. AIが「保全依頼を出したい」と言う
    ループは道具の印(REQUIRES_APPROVAL)を見て、実行しない。同じ返事で頼まれた、読むだけの道具は先に実行しておく。
  2. しおりを挟んで、ループの関数を抜ける
    保存するのは3つ:会話の履歴、済んだ道具の結果、承認待ちの依頼。保存先は画面の状態(st.session_state)。
  3. 画面に承認カードを出し、質問の入力欄をロックする
    装置・件名・優先度・内容を見せ、「承認して登録」「登録しない」の2つのボタン。
  4. 押されたら、しおりのところから続ける(resume_after_approval)
    承認なら登録して依頼番号を返す。登録しないなら「登録しなかった」(rejected_by_user)と返す。済んでいた結果と1通にまとめてAIに返し、ループを再開する。

承認が要る道具を増やすときは、tools.py の REQUIRES_APPROVAL に名前を足すだけ。ループ側は直さなくてよい。

8. 失敗したとき

基本の考え方は「失敗を捨てずにAIに伝える」と「アプリは落とさない」の2つです。失敗を伝えると、AIは別の調べ方を考えたり、「調べられなかった」と正直に答えたりできます。

起きたことどうなるか
見つからない(台帳に無い装置、マニュアルの無い型番)エラーにせず空の一覧を返す → AIは「見つからなかった」と答える(作り話をしない)
台帳に無い設備IDで依頼しようとした「失敗」の印(is_error)を付けて理由を返す → AIは調べ直すか、登録できなかったと伝える
DBが開けないなど、プログラムの例外「失敗」の印を付けて例外の内容を返す。アプリは落ちない
定義に無い道具の名前が来た「失敗」の印を付けて「その道具はありません」と返す
AIが道具を呼び続ける10周で止めて、画面に理由を出す
回答が長すぎて打ち切られた/AIが回答を控えた途中の返事は履歴に足さずに止める(履歴の形を崩さない)。回答を控えたときは、別のモデルに引き継ぐ設定もある
APIのエラー(キー違い・回数制限・接続)種類ごとに分けて理由を出す。アプリは落ちない

このうち「承認で止まって再開」「失敗をAIに返す」「10周で止まる」「打ち切りで履歴を崩さない」は、偽物のAPIを使ったテスト(tests/test_agent_offline.py、6件)で確かめてある。

9. ログ(記録)

作業日報のようなものです。質問ごとに1ファイル(logs/trace_日時.jsonl)に、1行1件で残します。画面の「調べた手順」にも同じ内容が出ます。

記録の種類残すこと
AIに聞いた(api_call)何周目か、AIの返事の種類、使ったトークン数(≒料金)、かかった秒数
道具を使った(tool_call)道具の名前、入力、見つかった件数、結果の先頭、失敗したか、秒数
人が判断した(approval)登録したか、しなかったか
終わった(final)完了か停止か、回答、トークン数の合計

本番で見るなら:1つの質問あたりの周回数・料金・時間、道具の失敗率、承認の却下率、10周で止まった回数。却下が多い道具や、上限で止まる質問は、道具の説明文やプロンプトを直す候補になる。

10. 用語の例え

用語例え技術的に言うと
Tool Use(Function Calling)AIが「この道具で調べて」と頼めるしくみLLMに関数の定義を渡し、呼び出しの判断をさせる仕組み
ツールの定義道具に貼るラベルname・description・input_schema を定義し、strict を付けた
ループ伝令係stop_reason で分岐するエージェントループを自前で実装した
tool_result道具の結果を届ける封筒tool_use_id を対応させて、結果を1つの user メッセージにまとめて返す
is_error封筒に貼る「失敗」のシール失敗を例外で握りつぶさず、is_error 付きの結果としてモデルに返す
承認待ちしおりを挟んで閉じる承認が要るツールでループを抜け、状態を保存して、承認後に再開する
トークン文字数のような料金の単位ターンごとの入出力トークンをログに残し、コストを追える