このマニュアルでは、すでに手元にある HTTP エンドポイントを、Perxona エージェントが呼び出せるツールに変える方法を示します。そして同じくらい重要なこととして、LLM がいつ・どのように使うべきかを実際に理解できるように、それをどう書くか を解説します。
1. LLM はツールをどう「見る」か
エージェントが動作するとき、Perxona はモデルにツールの一覧を渡します。各ツールは本質的に次のような形をしています(OpenAI や Anthropic が内部で使っているのと同じ形です)。
{
"name": "verb_noun",
"description": "What the tool does, and when the model should reach for it.",
"parameters": { /* the INPUT JSON Schema */ }
}
毎ターン、モデルはそのテキストだけを使って自問します。
- そもそもツールを呼び出すべきか? → name + description によって決まります。
- どれを? → 各 description が互いにどれだけ明確に区別されているか によって決まります。
- どんな引数で? → 入力スキーマ(フィールド名、型、
required、説明、enum、デフォルト)によって決まります。 - 何が返ってきたか/ユーザーに何を伝えるか? → 出力スキーマ が助けになります(これにより どのフィールドが返るか、それぞれの型が何かがわかります)。
つまり、制作者としてのあなたの仕事は、その 4 つを明確に書くことです。それがこの技芸のすべてです。
呼び出し時に実際に起こること(内部の動き)
呼び出すと判断し、入力スキーマに沿った引数を生成"] B["Perxona が引数を検証し(JSON Schema → Pydantic)、
シークレットを注入して HTTP リクエストを送信"] C["あなたのサーバーが処理し JSON を返す"] D["Perxona が JSON を LLM に戻し
(出力スキーマが解釈を助ける)、
LLM がユーザー向けの返答を書く — あるいは別のツールを呼ぶ"] A --> B --> C --> D
あなたが作るのは、サーバーと 4 つのテキスト/形のシグナルだけです。検証、シークレットの注入、HTTP 呼び出しは Perxona が行います。
2. Perxona における 2 つの構成要素
ツールのセットアップは、必ず 2 つのオブジェクト で構成されます。
| オブジェクト | その正体 | そこに入れるもの | LLM はそれを見るか? |
|---|---|---|---|
| OutboundAPI | 接続。サーバーの所在 + 認証方法 | ベース URL、シークレット(API キー) | いいえ — インフラのみ |
| CallFunc | エージェントが呼び出せる ツール | 名前、説明、メソッド、パス、入力スキーマ、出力スキーマ | はい — これが契約です |
- バックエンドごとに OutboundAPI を 1 つ 作成します(1 つのベース URL + 1 組のシークレット)。
- CallFunc を 3 つ 作成します(関数ごとに 1 つ)。いずれもその OutboundAPI を指すようにします。
CallFunc は Storyboard の Panel の中 に存在するため、ツールはそれが意味をなす会話状態(パネル)でのみ利用可能にできます。
3. ツールをセットアップする
始める前に必要なもの
Perxona はクラウドからあなたのエンドポイントを呼び出します。管理画面を開く前に、次のものが必要です。
- サーバーの公開 HTTPS ベース URL — 自分のマシン上にしか存在しないアドレスには到達できません。
- サーバーがリクエストごとに検証する認証シークレット(API キー、bearer トークン、あるいは本当に公開のエンドポイントであれば不要)。
ステップ 1 — OutboundAPI(接続)を作成する
管理画面(Backend Core / Outbound API)で、バックエンドごとに 1 件作成します。
| フィールド | 何を入れるか |
|---|---|
| Base URL | エンドポイントがぶら下がる scheme + host。個々のパスは各 CallFunc 側であり、ここではありません。 |
| Secret type | API_KEY、Bearer、または None。 |
| Header name | サーバーが認証情報を読み取るヘッダー。 |
| Header value | 認証情報そのもの — 暗号化して保存され、呼び出し時に注入されます。モデルがそれを見ることはありません。 |
同じバックエンドを叩く CallFunc はすべてこの 1 件を指すので、キーのローテーションやホストの移転は、ツールごとではなく 1 か所の編集で済みます。
ステップ 2 — CallFunc(ツール)を作成する
エージェントに実行させたい操作ごとに、CallFunc を 1 つ追加します。
| フィールド | 何を入れるか | LLM から見える? |
|---|---|---|
| Type | OUTBOUND_API |
いいえ |
| Name | 互いに区別できる verb_noun(§4.1) |
はい |
| Method / Path | HTTP メソッドと、OutboundAPI のベース URL 配下のパス | いいえ |
| Description | 何をするかと、いつ使うか(§4.2) | はい |
| Input schema | 引数の JSON Schema(§4.3) | はい |
| Output schema | 返ってくる内容の JSON Schema(§4.4) | はい |
ツールの数は少なく、互いに明確に区別できるように保ちましょう。説明が重なる 2 つのツールは、モデルにどちらかを推測させることになり、ときどき外します。
ステップ 3 — パネルでテストする
パネルの会話を開き、自分のスキーマの語彙ではなく、実際のユーザーが使う言い方でリクエストしてみてください。次の 3 点を、この順で見ます。
- そもそも呼び出すか。 呼ばないなら、説明が引き金を示せていません。
- 正しいツールを呼ぶか。 違うなら、2 つの説明が重なっています。
- 引数は正しいか。 違うなら、フィールドの説明にフォーマット・enum・
requiredが足りていません。
よくある症状と対処は第 6 節にまとめてあります。
4. 技芸: LLM が理解できる説明とスキーマを書く
ここが、エージェントが賢く感じられるか、それとも間抜けに感じられるかを左右する部分です。いくつかの経験則を、ビフォー/アフターつきで示します。
4.1 Name = モデルが照合する動詞
明確な verb_noun を使いましょう。動詞は何をするかを、名詞は何に対して働くかを表します。名前を互いに区別できるように保ち、モデルが似た 2 つのツールの間で迷わなくて済むようにします。
4.2 Description = 何であるか だけでなく いつ使うか
説明は、モデルが呼び出すかどうかを判断するたびに、毎ターン 読まれます。何をするかと、その引き金(「次のときに使う…」)、加えて制約があればそれを書きましょう。
| ❌ 曖昧 | ✅ 明確 |
|---|---|
| 「照会のエンドポイント。」 | 「<キー> で <エンティティ> を照会する。<フィールド> で絞り込み可。<フィールド> を返す。Use this when ユーザーが <引き金となる状況> を尋ねたとき。」 |
| 「レコードを作成する。」 | 「<必須フィールド> から <エンティティ> を作成する。Use only when ユーザーが明確に作成を求めたときのみ。 新しい id を含む確認を返す。」 |
コツ。 - 何を返すか をフィールドごとに書きましょう。そうすればモデルは、目の前の質問にそのツールで答えられることを把握できます。 - 否定の領域(「ユーザーが明確に求めたときのみ」)を明示し、早すぎる呼び出しや偶発的な呼び出しを止めましょう — 特に書き込みでは重要です。 - 実装の詳細(DB、フレームワーク)を書き連ねないこと。モデルはそれを気にしませんし、モデルが推論に使うコンテキストを無駄に消費します。
4.3 入力スキーマ = 引数の契約
各プロパティの説明は、モデルがそのフィールドを埋めるために使うヒントです。モデルはあなたの言い回しを真似るので、フォーマット については具体的に書きましょう。
- フォーマット。
"Date, YYYY-MM-DD."や"Local start time, 24h HH:MM."と書けば、モデルは"next Tuesday"や"4 PM"ではなく2026-06-11や16:00を出力するようになります。 required。 呼び出しに不可欠なフィールドを列挙します。モデルはそれらが揃うまでユーザーに尋ね続けます。- デフォルトと範囲。
default、minimum、maximumを持つ数値フィールドは — モデルがそれを省略でき、不正な値はサーバーに届く前に拒否されます。 - Enum は強力です。
{"type":"string","enum":["confirmed","tentative"]}はモデルを妥当な選択肢に制約します。 - フラットで小さく保つこと。 深くネストした入力は、モデルが確実に埋めるのが難しくなります。
4.4 出力スキーマ = モデルが結果をどう読むか(そして、なぜ追加を求められたか)
呼び出しのあと、モデルはあなたの JSON レスポンスを読みます。出力スキーマは、どんなフィールドが存在し、それらが何を意味するか をモデルに伝えるので、モデルは次のことができます。
- 正しい値を返答に引き込む(例: リンクのフィールドをクリック可能なリンクとして提示する、または メッセージのフィールドをそのまま読み返す)。
- 型を理解する(件数のフィールドが数値で、タグのフィールドがリストであることを把握する)。
- 存在しないフィールドをでっち上げない。
各出力フィールドも、入力を説明するのと同じ要領で説明しましょう。リンクのフィールドが
string | null であることや、あるステータスのフィールドが「実際に書き込まれた」のか
「シミュレートされただけ」なのかを区別することを書いておくと、エージェントは実際に起きたこと以上に
言い過ぎることなく、確認メッセージを正直に表現できます。
4.5 黄金律
5. 安全性と UX のつまみ
| つまみ | 何をするか | 用途 |
|---|---|---|
| Secret type(API_KEY / Bearer / None) | 呼び出し時に注入される認証ヘッダー。暗号化して保存される | エンドポイントを非公開に保つ。キーを description に決して入れないこと |
| パネルスコープ | CallFunc は、追加したパネルの中にのみ存在する | ユーザーが「予約」状態になるまで予約ツールを隠す |
6. トラブルシューティング
| 症状 | 考えられる原因 | 対処 |
|---|---|---|
| モデルがツールを 決して呼ばない | 説明が曖昧すぎる/別のツールと重複している | 明確な「use this when…」の引き金を入れて説明を書き直す。名前を区別する |
| モデルが 誤った引数 で呼び出す | フィールドの説明が不明確、フォーマット/enum の欠如 | description、フォーマット、enum、required、デフォルトを追加する |
| モデルが 書き込みを繰り返す、またはループする | いつ呼び出すべきでないかを説明が示していない | 説明の否定の領域を引き締める。ツールを本来のパネルにスコープする |
| 公開 URL が 404/タイムアウト | ベース URL が変わった、またはサーバーが落ちている | OutboundAPI のベース URL と、そのホストが自分のネットワークの外から到達できるかを再確認する |
7. Perxona CallFunc の特長
ここまでは、あなたが書く契約の話でした。この節では、プラットフォームがそれで何をするのか、そしてこのやり方の境界がどこにあるのかを扱います。
得られるもの
- 書くコードもホストするコードもない。 ベース URL と JSON Schema を貼り付けるだけで、任意の HTTP API がツールになります。既存のバックエンドは数分でエージェントのツールになり、その間にアダプターのサービスを挟む必要はありません。
- 全部入り。 暗号化されたシークレット、ツールごとの利用回数制限、human-in-the-loop の確認、コンテキストのテンプレート化、text-to-SQL の安全性、ロギング、マルチテナントのスコープは、すべてプラットフォームが提供します。
- 緊密な製品統合。 ツールはペルソナとストーリーボードのフローの中に存在し、パネルスコープ化できます —— それが意味を持つ会話状態でのみ利用可能にできます —— そしてメモリ、ガードレール、会話トランスクリプトと同じパイプラインに乗ります。
- 第一級フィールドとしての出力スキーマ。 何が返ってくるかを宣言でき、それがモデルの結果解釈を助け、実際に起きたことについて返答を正直に保ちます。
境界はどこか
- HTTP の 1 往復。 ストリーミングも、長時間実行のジョブも、ステートフルなツールセッションもありません。
- 事前に設定する。 ツールは管理画面で設定し、実行時の動的な探索はありません。ツールを変えるには管理画面で編集します。
- エンドポイントは自分でホストする。 Perxona から到達できる必要があり、その稼働時間、レイテンシ、タイムアウト、TLS はあなたの責任です。
- JSON Schema はシンプルに。 入出力は JSON Schema(Draft 2020-12)を使います。あまりに特殊なスキーマ機能はうまく変換されないことがあります。フラットでシンプルなほうが、そもそもモデルにとっても良い形です。
8. 1 ページの総まとめ
- 2 つのオブジェクト。 OutboundAPI を 1 つ(URL + API キー)+ 関数ごとに CallFunc を 1 つ (name、description、メソッド、パス、入力スキーマ、出力スキーマ)。
- モデルが見るのは name + description + 入力スキーマ + 出力スキーマ だけ — 賢い見知らぬ人に向けて書きましょう。
- Description = 何をするか + いつ使うか(+ 何を返すか、+ してはいけないこと)。
- 入力スキーマ = フィールド名、型、
required、フォーマット、デフォルト、enum。 - 出力スキーマ = 何が返ってくるか。これによりモデルが結果を正しく読みます。
- これは HTTP + マネージドのガードレールで、コード不要 — すでに呼び出せるエンドポイントが、そのままエージェントの使えるツールになります。