AI 関数
会話中に呼び出せるカスタムのバックエンドロジックで AI エージェントを拡張します。
AI 関数を使う理由
AI エージェントは質問に答えるだけでは不十分です。注文状況の参照、データベースの更新、ドメイン固有の計算の実行、外部 API の呼び出しなどを行う必要があります。モデル単体ではそれらを自力で行う方法を知りません。
AI 関数がない場合、エージェントはモデルがすでに知っていることに限定されます。AI 関数があれば、会話の要件に応じていつでもバックエンドコードを呼び出せます。
// Backend: define the function
@aiFunction<{ shipName: string }>(
'Returns the list of pirates on a given ship. Call when the user asks about a ship crew.',
[{ name: 'shipName', description: 'The name of the ship', type: 'string', required: true }],
)
async listPiratesOnShip(params: { shipName: string }): Promise<string> {
// Your custom logic: query a database, call an API, run a calculation, etc.
const { shipName } = params;
const crew = await this.lookupCrew(shipName);
return crew.join(', ');
}
// Frontend: pass the function to the agent and ask a question
const response = await squid
.ai()
.agent('pirate-agent')
.ask('Who is on the Black Pearl?', {
functions: ['listPiratesOnShip'],
});
Agent Studio または setAgentOptionInPath を使って、リクエストごとに渡す代わりに関数をエージェントに永続的に追加することもできます。
エージェントは関数の description を読み、いつ呼び出すべきかを判断し、その結果をレスポンスに組み込みます。
概要
AI 関数は、@aiFunction でデコレートされた Squid Service 内のメソッドです。これらを AI agent にアタッチすると、関数の description とユーザーのプロンプトに基づいて、会話中にエージェントが呼び出せるようになります。
AI 関数を使うべきとき
| ユースケース | 推奨 |
|---|---|
| エージェントがカスタムのサーバーサイドロジックを呼ぶ必要がある | AI function |
| エージェントが接続済みデータベースの読み書きをする必要がある | データベースコネクターを使用、またはカスタムクエリロジック用に AI function |
| エージェントが接続済みサービス(CRM、カレンダー、API など)にアクセスする必要がある | Connected integration を使用 |
| エージェントが MCP 経由で外部ツールに接続する必要がある | MCP を使用 |
| エージェントがアップロード済みドキュメントを検索する必要がある | Knowledge Bases を使用 |
仕組み
SquidServiceを拡張したクラス内のメソッドを@aiFunctionでデコレートします- SDK またはコンソールの Agent Studio から、名前でその関数をエージェントにアタッチします
- ユーザーがメッセージを送ると、エージェントが関数の description をプロンプトと照合して評価します
- 関数が関連するとエージェントが判断した場合、AI が生成したパラメータ値で関数を呼び出します
- 関数はバックエンドで実行され、文字列結果を返します
- エージェントは結果をレスポンスに組み込みます
クイックスタート
前提条件
squid init-backendで初期化された Squid backend プロジェクト@squidcloud/backendパッケージがインストールされていること- 作成済みの AI agent
Step 1: AI 関数を作成する
Squid Service に @aiFunction デコレータ付きのメソッドを追加します。
import { SquidService, aiFunction } from '@squidcloud/backend';
export class AiService extends SquidService {
@aiFunction<{ city: string }>('Returns the current weather for a given city. Call when the user asks about weather.', [{ name: 'city', description: 'The city name', type: 'string', required: true }])
async getWeather(params: { city: string }): Promise<string> {
const { city } = params;
// Replace with your actual weather API call
return `The weather in ${city} is 72°F and sunny.`;
}
}
Step 2: バックエンドをデプロイする
ローカル開発では次を実行します。
squid start
クラウドへデプロイする場合は、deploying your backend を参照してください。
デプロイ後、関数はコンソールの Agent Studio の Abilities に表示されます。
Step 3: 関数付きでエージェントを呼び出す
const response = await squid
.ai()
.agent('my-agent')
.ask("What's the weather in Tokyo?", {
functions: ['getWeather'],
});
console.log(response);
エージェントはユーザーが天気について尋ねたことを認識し、{ city: "Tokyo" } で getWeather を呼び出して、その結果をレスポンスに含めます。
setAgentOptionInPath を使って関数をエージェントに永続的に追加すれば、リクエストごとに渡す必要がなくなります。
await squid.ai().agent('my-agent').setAgentOptionInPath('functions', ['getWeather']);
// Now the agent always has access to getWeather
const response = await squid.ai().agent('my-agent').ask("What's the weather in Tokyo?");
コアコンセプト
@aiFunction デコレータ
デコレータは必須の引数を 2 つ受け取ります。
description(string): エージェントにこの関数をいつ呼ぶべきかを伝えます。曖昧なラベルではなく、明確な指示として書いてください。params(array): 関数呼び出し時にエージェントが提供すべきパラメータを定義します。
@aiFunction<{ productId: string; quantity: number }>(
'Updates the stock quantity for a product. Call when the user wants to adjust inventory.',
[
{ name: 'productId', description: 'The product ID', type: 'string', required: true },
{ name: 'quantity', description: 'Amount to add (negative to subtract)', type: 'number', required: true },
],
)
async updateStock(params: { productId: string; quantity: number }): Promise<string> {
// ...
}
または、デコレータに単一の options オブジェクトを渡すこともできます。
@aiFunction({
description: 'Updates the stock quantity for a product.',
params: [
{ name: 'productId', description: 'The product ID', type: 'string', required: true },
{ name: 'quantity', description: 'Amount to add (negative to subtract)', type: 'number', required: true },
],
})
async updateStock(params: { productId: string; quantity: number }): Promise<string> {
// ...
}
パラメータ定義
params 配列内の各パラメータは次のフィールドをサポートします。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
name | string | Yes | パラメータ名。関数の params オブジェクト内のキーと一致させます |
description | string | Yes | エージェントにどの値を渡すべきかを伝えます |
type | string | Yes | データ型: 'string', 'number', 'boolean' など |
required | boolean | Yes | エージェントがこの値を必ず提供しなければならないかどうか |
enum | any[] | No | 値を許可された選択肢の集合に制限します |
特定の選択肢のみ有効な場合は enum を使って値を制約します。
@aiFunction('Saves a section in a document', [
{
name: 'sectionId',
type: 'string',
description: 'Which section to update in the document',
required: true,
enum: ['introduction', 'background', 'methodology', 'results', 'conclusion'],
},
{
name: 'content',
type: 'string',
description: 'The content of the section',
required: true,
},
])
async saveSection(params: { sectionId: string; content: string }): Promise<string> {
const { sectionId, content } = params;
const docRef = this.squid.collection('documents').doc('my-doc');
await docRef.update({ [sectionId]: content });
return 'Section saved: ' + sectionId;
}
戻り値
AI 関数は Promise<string> を返す必要があります。エージェントはこの文字列を受け取り、レスポンスを組み立てるために使用します。明確で簡潔な結果を返してください。
// Good: returns useful information the agent can relay
return 'Order #1234 shipped on March 5. Tracking number: ABC123';
// Bad: returns raw JSON the agent has to interpret
return JSON.stringify(orderObject);
Attributes
Attributes を使うと、AI 関数を特定の connector type にバインドし、そのコネクターの組み込み機能を独自のカスタムロジックで拡張できます。その type の connector をエージェントに追加すると、コネクターのデフォルト動作と並んで関数が自動的に含まれます。
たとえば、データベースコネクターはすでにエージェントが AI でデータをクエリできるようにしています。しかし、エージェントに特定の方法で一貫してクエリさせたい場合は、そのコネクター type に属性を付けた AI 関数を作成できます。
@aiFunction({
description: 'Retrieves recent orders for a customer from the PostgreSQL database',
params: [
{
name: 'customerEmail',
description: 'The email address of the customer',
type: 'string',
required: true,
},
],
attributes: {
integrationType: ['postgres'],
},
})
async getCustomerOrders(
{ customerEmail }: { customerEmail: string },
{ integrationId }: AiFunctionCallContextWithIntegration,
): Promise<string> {
// Custom query logic.
//
// Squid provides "Query with AI" where the agent can write the query and execute it to
// accomplish a task, but if you want it to consistently query in a certain way, you can write
// an AI Function that you can instruct it to call instead.
}
PostgreSQL connector をエージェントに追加すると、この関数は自動的に含まれます。
connector type に Attributes が付与された関数は、Agent Studio の AI Functions リストには表示されません。エージェントへの含め方は connector によって処理されます。
Categories
Categories を使うと、Agent Studio 内で AI 関数をグルーピングして整理しやすくできます。
@aiFunction({
description: 'Get all new user reviews from the product listing on Amazon.',
params: [
{
name: 'productId',
description: 'The ID of the listing on Amazon, e.g. "B094D3JGLT" for the URL "https://www.amazon.com/dp/B094D3JGLT"',
type: 'string',
required: true,
},
{
name: 'cutoffDate',
description: 'The cutoff date. Only reviews newer than this date should be returned. Use ISO8601 format. Defaults to returning all reviews.',
type: 'string',
required: false,
},
],
categories: ['Data Gathering'],
})
async getProductReviews(
{ productId, cutoffDate }: { productId: string; cutoffDate?: string },
{ integrationId }: AiFunctionCallContextWithIntegration,
): Promise<string> {
// Your logic to gather the user reviews.
}
これにより、getProductReviews は AI Functions リスト内の "Data Gathering" カテゴリの下に表示されます。複数のカテゴリを指定でき、関数はそれぞれに表示されます。
パラメータ値の上書き
エージェントによっては、AI に決めさせるのではなく特定のパラメータ値を固定したい場合があります。predefinedParameters を使ってパラメータを上書きできます。AI は上書きされたパラメータが存在することを知らず、その値を設定できません。
たとえば、先ほどの saveSection 関数を使って introduction セクションだけを更新するエージェントを作れます。
chat widget から:
<squid-chat-widget
...
squid-ai-agent-chat-options={{
functions: [{
name: 'saveSection',
predefinedParameters: { sectionId: 'introduction' }
}]
}}
...
>
</squid-chat-widget>
SDK から:
const result = await squid
.ai()
.agent('my-agent')
.ask('Save that content.', {
functions: [
{
name: 'saveSection',
predefinedParameters: { sectionId: 'introduction' },
},
],
});
エージェントが提供できるのは content パラメータのみです。sectionId は常に 'introduction' になります。
AI 関数にコンテキストを渡す
AI が生成する params に加えて、context オブジェクトを使って独自の値を AI 関数に渡せます。これは、ドキュメント ID、ユーザー設定、セキュリティ関連の値など、AI に制御させるべきではないデータに便利です。
context には 2 つのスコープがあります。
agentContext: エージェントが行うすべての AI 関数呼び出しに渡されます。ctx.agentContextで参照します。functionContext: 特定の関数にだけ渡されます。ctx.functionContextで参照します。
例
saveSection 関数をベースに、document ID をエージェントレベルで固定し、保存前にコンテンツから内部コードネームをマスクしたいとします。
import { SquidService, aiFunction, AiFunctionCallContext } from '@squidcloud/backend';
const SECTION_IDS = ['introduction', 'background', 'methodology', 'results', 'conclusion'] as const;
type SectionId = (typeof SECTION_IDS)[number];
interface DocumentIdAgentContext {
documentId: string;
}
interface RedactionFunctionContext {
codenameList: string[];
}
class DocumentService extends SquidService {
@aiFunction('Saves a section in a document', [
{
name: 'sectionId',
type: 'string',
description: 'Which section to update in the document',
required: true,
enum: [...SECTION_IDS],
},
{
name: 'content',
type: 'string',
description: 'The content of the section',
required: true,
},
])
async saveSection({ sectionId, content }: { sectionId: SectionId; content: string }, ctx: AiFunctionCallContext<RedactionFunctionContext, DocumentIdAgentContext>): Promise<string> {
const docRef = this.squid.collection('documents').doc(ctx.agentContext.documentId);
let censoredContent = content;
for (const censorWord of ctx.functionContext.codenameList) {
censoredContent = censoredContent.replaceAll(censorWord, 'REDACTED');
}
await docRef.update({ [sectionId]: censoredContent });
return 'Section saved: ' + sectionId;
}
}
クライアント側から chat widget を通じて context 値を渡します。
<squid-chat-widget
...
squid-ai-agent-chat-options={{
agentContext: { documentId: "document_controlled_by_this_agent" },
functions: [{
name: 'saveSection',
context: { codenameList: ['LITANIA', 'LEOPARD'] }
}]
}}
...
>
</squid-chat-widget>
または SDK から:
const result = await squid
.ai()
.agent('my-agent')
.ask('I want the "results" section to be "LITANIA has determined the answer to be 42".', {
agentContext: { documentId: 'document_controlled_by_this_agent' },
functions: [
{
name: 'saveSection',
context: { codenameList: ['LITANIA', 'LEOPARD'] },
},
],
});
この場合、"LITANIA" が codename list に含まれているため、保存される内容は "REDACTED has determined the answer to be 42" になります。
エラーハンドリング
AI 関数がエラーを throw すると、エージェントはそのエラーメッセージを受け取り、ユーザーに伝えるか、次の対応を判断できます。明確で説明的なエラーを投げてください。
@aiFunction<{ orderId: string }>(
'Looks up the status of an order.',
[{ name: 'orderId', description: 'The order ID', type: 'string', required: true }],
)
async getOrderStatus(params: { orderId: string }): Promise<string> {
const { orderId } = params;
const order = await this.squid.collection('orders').doc(orderId).snapshot();
if (!order) {
throw new Error(`Order ${orderId} not found`);
}
return `Order ${orderId}: ${order.status}, shipped ${order.shippedDate}`;
}
よくある問題
| 問題 | 原因 | 解決策 |
|---|---|---|
| 関数が一度も呼ばれない | description がユーザーのプロンプトに一致しない | いつ呼ぶべきかが明確になるよう description を書き直す |
| パラメータ値が誤っている | パラメータ description が曖昧 | 具体的な description を追加し、enum で値を制約する |
| エージェントが関数を見つけられない | functions オプションに関数名が渡されていない | ask 呼び出しで関数名を渡すか、Agent Studio で追加する |
| Agent Studio に関数が表示されない | 関数がクラウドにデプロイされていない | squid deploy でバックエンドをデプロイする |
ベストプラクティス
明確な description を書く
description は、エージェントが関数を正しく呼び出せるかどうかを左右する最重要要素です。いつ使うべきかを正確に伝える指示として書いてください。
// Good: specific and instructive
'Returns the shipping status and tracking number for an order. Call when the user asks about order status, delivery, or tracking.';
// Bad: vague
'Gets order info';
パラメータを慎重に設計する
- 関数が動作するのに不可欠な値にのみ
required: trueを使う - 有効な値が既知の集合なら
enumを設定する - パラメータ description に、使用すべきフォーマットを明記する(例: "ISO8601 date", "email address")
戻り値は情報量を保つ
エージェントは返された文字列を使ってレスポンスを組み立てます。生データ構造ではなく、人間が読める情報を返してください。
入力を検証する
AI がパラメータ値を生成する場合でも、関数内で検証してください。AI は想定外の値を出すことがあります。
async updateQuantity(params: { quantity: number }): Promise<string> {
const { quantity } = params;
if (!Number.isFinite(quantity) || quantity < 0) {
throw new Error('Quantity must be a non-negative number');
}
// ...
}
次のステップ
- 関数のアタッチやエージェント設定については AI agent documentation
- エージェントを外部ツールサーバーに接続するには MCP
- AI 関数を使った完全な例は AI home maintenance tutorial