注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。
この高度なカスタマイズガイドに進む前に、次の概念を理解していることを確認してください。
このページでは、次の高度なカスタマイズオプションについて説明します。
systemPrompt 関数は、現在のエージェントの状態を受け取ります。SDK はモデルリクエストごとにこの関数を評価するため、状態が更新されると、次のリクエストで使用される指示が変わります。たとえば、エージェントはセッションに保存された対象ユーザーに合わせて説明を調整できます。
Copied!1 2 3 4 5 6 7import { SystemPromptRenderResult } from "@palantir/agents"; // エージェントの状態に `audience` がある場合の defineAgent({ ... }) 内: systemPrompt: state => SystemPromptRenderResult.ready([ { type: "text", text: `Explain the answer for ${state.audience}.` }, ]),
LanguageModel を作成するmodel オプションには、LanguageModel を実装する任意のオブジェクトを指定できます。たとえば、2個のモデルを組み合わせ、最初のモデルが終了したレスポンスを返した場合に、バックアップのモデルを使用できます。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14import { type LanguageModel } from "@palantir/agents"; // primaryModel と backupModel は LanguageModel の値です。 const languageModelWithBackup: LanguageModel = { async generateResponse(args) { const response = await primaryModel.generateResponse(args); return response.status.type === "terminated" ? backupModel.generateResponse(args) : response; }, }; // defineAgent({ ... }) 内: model: languageModelWithBackup,
独自のモデルクライアントを使用して generateResponse を実装することもできます。SDK のメッセージとツールをそのクライアントのリクエスト形式に変換し、レスポンスを SDK のアシスタントパートとステータスに変換します。これにより、エージェントから新しいオープンソースモデルや、独自にファインチューニングしたモデルを呼び出せます。
組み込みのプロバイダーコンストラクターは、サポート対象のプロバイダーについて、この変換をそのまま処理します。
model に関数を渡すことで、実行時にモデルを動的に選択します。イベントによってその状態が変わると、以降のリクエストで別のモデルを使用できます。
Copied!1 2 3 4 5 6import { z } from "zod"; // fastModel と detailedModel は LanguageModel の値です。 // defineAgent({ ... }) 内: agentStateSchema: z.object({ useDetailedModel: z.boolean() }), model: state => state.useDetailedModel ? detailedModel : fastModel,
組み込みの各プロバイダーコンストラクターは、そのプロバイダーがサポートする設定を modelSettings で受け取ります。一般的な設定には、推論、サンプリング温度、レスポンスの長さがあります。
Copied!1 2 3 4 5 6 7 8 9 10 11 12import { Aliases } from "@osdk/functions"; import { anthropic, openAi } from "@palantir/agents"; const anthropicModel = anthropic({ modelRid: Aliases.model("anthropicModel").rid, modelSettings: { max_tokens: 4096, temperature: 0.2 }, }); const openAiModel = openAi({ modelRid: Aliases.model("openAiModel").rid, modelSettings: { reasoning: { effort: "high" } }, });
設定はプロバイダーやモデルによって異なります。
コンテキスト項目は、型を持つセッション情報です。SDK は、ユーザーメッセージ、アシスタントメッセージ、ツールエラー項目を自動的に作成します。構造化データを保存し、モデルにどのように表示されるかを制御するには、zodContextItem でカスタム項目を定義します。その定義を contextItemDefinitions に登録します。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16import { Message, RenderResult, UserMessagePart, zodContextItem } from "@palantir/agents"; import { z } from "zod"; const WeatherResult = zodContextItem({ type: "weather-result", createArgsSchema: z.object({ city: z.string(), summary: z.string() }), dataSchema: z.object({ city: z.string(), summary: z.string() }), create: args => ({ data: args }), render: data => RenderResult.ready([ Message.user(UserMessagePart.text(`${data.city}: ${data.summary}`)), ]), }); // defineAgent({ ... }) 内: contextItemDefinitions: [WeatherResult],
create 関数は、保存するデータを初期化します。render 関数は、そのデータをモデルメッセージに変換します。項目がまだデータを待っている場合は、RenderResult.pending() を返します。項目の準備ができると、生成が再開されます。カスタムコンテキスト項目では、データを更新するイベントも定義できます。
tools オプションには、モデルリクエストごとに現在のエージェントの状態を受け取る関数を指定できます。その状態に基づいてツールを返します。状態が更新されると、以降のリクエストで提供されるツールが変わります。
Copied!1 2 3 4 5import { z } from "zod"; // defineAgent({ ... }) 内: agentStateSchema: z.object({ weatherEnabled: z.boolean() }), tools: state => state.weatherEnabled ? [WeatherTool] : [],
ツールは、結果とともにセッションイベントを返すことができます。たとえば、調査メモの表示テキストにコンテキスト項目IDが含まれていれば、エージェントはメモが役に立たなくなったときに、そのメモを非表示にできます。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29import { setContextItemOrder, UserMessagePart, zodSessionEvent, zodTool } from "@palantir/agents"; import { z } from "zod"; const HideContextItem = zodSessionEvent( "hide-context-item", z.object({ contextItemId: z.string() }), ); const HideNote = zodTool({ name: "hide_note", description: "Hide a research note that is no longer needed", argumentSchema: z.object({ contextItemId: z.string() }), emits: [HideContextItem], execute: async ({ contextItemId }) => ({ contextItems: [{ contextItemType: "@platform/user-message", createArgs: { parts: [UserMessagePart.text("Note hidden from context.")] }, }], events: [HideContextItem.create({ contextItemId })], }), }); // defineAgent({ ... }) 内: tools: () => [HideNote], eventDefinitions: [HideContextItem], handleEvent: (state, event) => ({ stateUpdates: [setContextItemOrder( state.contextItemOrder.filter(id => id !== event.payload.contextItemId), )], }),
contextItemOrder から最上位の項目を外すと、その項目は以降のモデルリクエストから除外されますが、セッションの状態には保持されます。エージェントは、その ID を再び順序に追加することで、項目を復元できます。
実行時間の長いツールでは、デフォルトの動作ではツールの進行状況を示すカスタム UI を表示できません。コンテキスト項目には、これを実現するためのフレームワークがあります。
Ready を表示するまで、ツールは完了としてマークされません。RenderResult.ready() を返します。たとえば、処理待ちのコンテキスト項目が結果を読み込んでいる間、アプリケーションで「東京行きのフライトを検索中…」と表示できます。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46import { Message, RenderResult, UserMessagePart, zodContextItem, zodContextItemEffect, zodContextItemEvent, zodTool, } from "@palantir/agents"; import { z } from "zod"; const FlightsReady = zodContextItemEvent("flights-ready", z.string()); const SearchFlights = zodContextItemEffect( "search-flights", z.string(), [FlightsReady], async (destination, dispatchEvent) => { dispatchEvent(FlightsReady.create(await findFlights(destination))); }, ); const FlightSearchResult = zodContextItem({ type: "flight-search", createArgsSchema: z.object({ destination: z.string() }), dataSchema: z.object({ destination: z.string(), result: z.string().nullable() }), eventDefinitions: [FlightsReady], create: ({ destination }) => ({ data: { destination, result: null }, effects: [SearchFlights.create(destination)], }), handleEvent: (data, event) => ({ data: { ...data, result: event.payload } }), render: data => data.result === null ? RenderResult.pending() : RenderResult.ready([Message.user(UserMessagePart.text(data.result))]), }); const FindFlights = zodTool({ name: "find_flights", description: "Find flights to a destination", argumentSchema: z.object({ destination: z.string() }), execute: async args => ({ contextItems: [{ contextItemType: FlightSearchResult.type, createArgs: args }], events: [], }), });
これは、カスタムツール読み込み UIと同じ、処理待ちのコンテキスト項目のパターンを使用します。効果でデータの読み込みを開始する代わりに、ツールはアプリケーションで表示する UserQuestion 項目を返します。人間が非同期に回答すると、アプリケーションはその回答を含むコンテキスト項目イベントを送出します。その後、項目が回答を表示し、モデルが処理を続行できるようになります。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29const AnswerProvided = zodContextItemEvent("answer-provided", z.string()); const UserQuestion = zodContextItem({ type: "user-question", createArgsSchema: z.object({ question: z.string() }), dataSchema: z.object({ question: z.string(), answer: z.string().nullable(), }), create: ({ question }) => ({ data: { question, answer: null } }), eventDefinitions: [AnswerProvided], handleEvent: (data, event) => ({ data: { ...data, answer: event.payload } }), render: ({ answer }) => answer === null ? RenderResult.pending() : RenderResult.ready([Message.user(UserMessagePart.text(answer))]), }); const AskUser = zodTool({ name: "ask_user", description: "Ask the user a question and wait for an answer", argumentSchema: z.object({ question: z.string() }), execute: async ({ question }) => ({ contextItems: [ { contextItemType: UserQuestion.type, createArgs: { question } }, ], events: [], }), });
Agent SDK では、エージェントは状態機械であり、キューで待機しているイベントを決定論的に処理して、状態を更新します。効果を使用すると、非同期処理を実行し、イベントを送出することで結果をエージェントに返せます。
このカスタム状態機械にフックする機能は、エージェントに決定論的ロジックを組み込めるため、Agent SDK の非常に強力な機能です。
カスタムイベントを使用すると、ユーザーはエージェントが実行する、型を持つ決定論的なステップを定義できます。イベントは、次の方法で送出できます。
イベントはキューに追加され、順番に処理されます。イベントハンドラーでは、次のことができます。
AgentState を更新するカスタム効果は、イベントハンドラーの外で非同期処理を実行します。イベントハンドラーは登録済みの効果を開始でき、その効果は処理が完了すると、別の登録済みイベントを送出します。
スケジュール調整エージェントは、会議の時刻を提案し、ユーザーが確認した後にカレンダーの招待を送信できます。確認イベントは、セッションをスケジュール調整中としてマークし、カレンダーサービスを呼び出す効果を開始します。招待が送信されると、効果はイベントを送出します。このイベントは、会議がスケジュールされたことを示すようにエージェントの状態を更新し、必要な情報をすべて追加します。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51import { setAgentState, zodSessionEffect, zodSessionEvent } from "@palantir/agents"; import { z } from "zod"; const MeetingDetails = z.object({ title: z.string(), startTime: z.string() }); // ユーザーが会議を確認したときにトリガーされるイベント const MeetingConfirmed = zodSessionEvent( "meeting-confirmed", MeetingDetails, ); // 招待が送信されたときにトリガーされるイベント const InvitationSent = zodSessionEvent( "invitation-sent", z.object({ meetingUrl: z.string() }), { type: "private" }, ); const SendInvitation = zodSessionEffect( "send-invitation", MeetingDetails, [InvitationSent], async (meeting, dispatchEvent) => { const meetingUrl = await createCalendarInvitation(meeting); dispatchEvent(InvitationSent.create({ meetingUrl })); }, ); // defineAgent({ ... }) 内: agentStateSchema: z.object({ status: z.string(), meetingUrl: z.string().nullable() }), eventDefinitions: [MeetingConfirmed, InvitationSent], effectDefinitions: [SendInvitation], handleEvent: (state, event) => { switch (event.type) { case MeetingConfirmed.type: return { stateUpdates: [setAgentState({ ...state.agentState, status: "scheduling", meetingUrl: null, })], // 招待を送信する効果を開始します effects: [SendInvitation.create(event.payload)], }; case InvitationSent.type: return { stateUpdates: [setAgentState({ ...state.agentState, status: "scheduled", meetingUrl: event.payload.meetingUrl, })], }; } },
患者向けのエージェントは、セッションの開始時に患者の完全な記録を読み込めます。createSession が読み込みを開始し、効果が記録を取得します。その結果として発生するイベントが、後続のツールやモデルリクエストで使用できるように、記録をエージェントの状態に保存します。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35import { getPatientData, PatientDataSchema } from "./patient-data"; import { setAgentState, zodSessionEffect, zodSessionEvent } from "@palantir/agents"; import { z } from "zod"; const PatientDataLoaded = zodSessionEvent( "patient-data-loaded", PatientDataSchema, { type: "private" }, ); const LoadPatientData = zodSessionEffect( "load-patient-data", z.object({ patientId: z.string() }), [PatientDataLoaded], async ({ patientId }, dispatchEvent) => { const patientData = await getPatientData(patientId); dispatchEvent(PatientDataLoaded.create(patientData)); }, ); // defineAgent({ ... }) 内: agentStateSchema: z.object({ patientData: PatientDataSchema.nullable() }), createSessionArgsSchema: z.object({ patientId: z.string() }), createSession: ({ patientId }) => ({ agentState: { patientData: null }, // 患者データをエージェントの状態に自動的に読み込みます effects: [LoadPatientData.create({ patientId })], }), eventDefinitions: [PatientDataLoaded], effectDefinitions: [LoadPatientData], handleEvent: (state, event) => ({ stateUpdates: [setAgentState({ ...state.agentState, patientData: event.payload, })], }),