Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KoogではじめるAIエージェント開発

Avatar for hiro hiro
November 01, 2025

 KoogではじめるAIエージェント開発

Kotlin Fest 2025の登壇資料です。
https://2025.kotlinfest.dev/timetable/1719040800_a/

Avatar for hiro

hiro

November 01, 2025
Tweet

More Decks by hiro

Other Decks in Programming

Transcript

  1. 自己紹介 • Nosho Hiroaki • Android Engineer/Kotlin歴が長い • 社内向けのAI/DXアプリの開発(フルスタック) •

    趣味: AIを使った個人アプリ 3 X: @hiroaki08181359 GitHub: hiroaki404 スライド資料
  2. AIエージェントとは?(1/3) "Agent" can be defined in several ways. Some customers

    define agents as fully autonomous systems that operate independently over extended periods, using various tools to accomplish complex tasks. Others use the term to describe more prescriptive implementations that follow predefined workflows. … by Anthropic Building effective agents https://www.anthropic.com/engineering/building-effective-agents 6 定義は様々 自律的に動く ツール 複雑なタスク ワークフロー
  3. AIエージェントとは?(3/3) 8 以前のAI Coding Coding Agent 🔎 🧠 🔧 🧠

    Read/Write/ Shell/Search.. Application Plan, Observe, Reasoning.. ClaudeCode等
  4. • 業務の自動化(文書作成、 経理処理、社内情報検索...) • カスタマーサービス • Deep Research ◦ 複数のエージェントが協調する

    リサーチ • BtoCアプリ(旅行AI、料理AI…) • (※ChatGPTやGeminiもAIエージェント) AIエージェントでできること 9 旅行AIエージェント
  5. AIエージェントを作るメリット • すでにある汎用的なAIエージェントは使えないのか? ◦ ChatGPT, Gemini, Claude Desktop, Gemini CLI,

    Claude Code… • 不安定な出力を制御し、特定タスクでの精度/効率を高める ◦ 汎用的なエージェントはときに不安定で効率が悪い ◦ 特定タスクに特化したエージェントワークフローで、安定した結果を得る ◦ 無駄な出力を抑えて費用の節約にもなる 10
  6. • ✅ Pure Kotlinであること ◦ (AI関連のフレームワークはPythonが多い) • ✅ 静的型付けでありシステム開発に有利 ◦

    プロトタイプ以上の、信頼性・保守性が求められるシステムに • ✅ AIコードとアプリケーションのコードをすべてKotlinで作れる ◦ AIがPythonだとアプリケーションのコードで言語が違う問題 ◦ 接続の手間、開発者が複数の言語を読む負荷 ◦ KotlinだとAI、Backend、UIすべてKotlinで作れる Pure Kotlin framework(1/2) 14
  7. • ✅ Kotlin-DSLを使ったワークフロー(グラフ構造)の表現 ◦ Nodeの関係や処理の流れが分かりやすい ◦ 他のフレームワークにはない良さ edge(nodeStart forwardTo nodeCallLLM)

    edge(nodeCallLLM forwardTo nodeExecuteTool onToolCall { true }) edge(nodeCallLLM forwardTo nodeFinish onAssistantMessage { true }) edge(nodeExecuteTool forwardTo nodeSendToolResult) edge(nodeSendToolResult forwardTo nodeFinish onAssistantMessage { true }) edge(nodeSendToolResult forwardTo nodeExecuteTool onToolCall { true }) Pure Kotlin framework(2/2) 15
  8. Koog Overview(1/2) • ✅ 幅広いモデル ◦ Google, OpenAI, Anthropic, OpenRouter,

    Ollamaに対応(ローカルLLMも可) • ✅ シンプルな構築から複雑なカスタマイズまで ◦ 事前定義されたワークフローで簡単にエージェントを構築 • ✅ 本番環境での運用 ◦ チェックポイント、副作用のあるツールのロールバックがあり 障害に強い 16
  9. Koog Overview(2/2) • ✅ Multiplatform support ◦ Kotlin Multiplatformに対応(JVM, JS,

    WasmJS, iOS, 他も追加予定) • ✅ Server Side Support ◦ Ktor, Spring boot plugin • IDE support ◦ Jetbrainsの製品でサポートが入る予定 17
  10. 他のフレームワーク LangChain LangGraph AutoGen Koog Genkit Firebase AI Logic 19

    Agent Developer Kit Bedrock LangChain4j and more.. CopilotStudio Dify SpringAI Mastra Strands Agents Embabel AgentKit フレームワーク選定の観点を取り上げ、 Koogの立ち位置を捉える VoltAgent AgentCore Agent Service Agent Engine Vertex AI CrewAI
  11. LangChain/LangGraph 21 • ☑ リソースや活用事例が多い ◦ 機能が豊富、基準となるフレームワーク • Python/JavaScript/TypeScript •

    LangChain/LangGraph(OSS) + LangSmith(Commercial) ◦ LangChain: シンプルなチェーン、LCEL記法(パイプで処理を繋ぐ)、エージェント ◦ LangGraph: グラフ構造の複雑なワークフロー
  12. Cloud Vendor Framework(Google, Amazon, Microsoft) • エージェントフレームワーク : Agent Developer

    Kit, Autogen, Strands Agents • モデルのAPI: Vertex AI, Azure OpenAI, Bedrock • プラットフォーム(deploy,no-code):Agent Engine, Agent Service, AgentCore, Bedrock Agent • 「モデルのAPI」は他のフレームワークとの 併用可能 ◦ KoogもBedrockと統合機能を提供 • ☑ クラウドと親和性が高い ◦ 安全性、セキュリティ、デプロイ、ポータル機能(Playground、トレース)を気軽に利用可能 • 特定のクラウドにある程度依存する可能性がある ◦ モデルの制約、クラウドの知識もある程度必要 • (※大雑把な分類なのでご注意ください。クラウドに依存することによる制約は限定的なこともあります ) 24
  13. 他のフレームワークと比較したKoogの特徴 • ✅ プログラミング言語: Kotlin • ✅ 開発しやすさ、スケーラビリティ • ✅

    豊富な機能、実用面を重視した機能 • ✅ 再利用可能なワークフロー、本番運用、Kotlin DSL、Multiplatform • ➡ クラウドベンダーに依存しないフレームワーク ◦ Koogはエージェントを構築するライブラリ ◦ 🚧 クラウド連携も計画されいてる(Agent Engine, AgentCore) • 🚧 開発環境: 現状単独の開発支援のツールは少ないので他と組み合わせる ◦ ただしIDEのデバッグツールが近日公開される予定だそうです 25
  14. 🧪 開発環境 • 開発環境は早めに整える ◦ Langfuseと簡単に統合し トレース可能 ▪ ※OpenTelemetryに対応 ◦

    KotlinNotebookはLLM応答をさっ と確認、出力を保存/共有 26 Langfuse https://langfuse.com/ KotlinNotebook
  15. ⚠ Risk • APIの不正利用 ◦ API Keyはハードコードせず安全に管理 • Prompt Injection

    ◦ 不正な命令でシステムを乗っ取る攻撃 • Harmful Output ◦ 倫理的に良くない等有害なコンテンツの生成 • (※Koogに限らず他のフレームワークでも注意する) • 対策: ガードレール、多層防御の考え方... 27
  16. 📒 Catch Up • ✅ 公式リソースが充実していて始めやすい • 公式ドキュメント(設計のベストプラクティスも ) ◦

    https://docs.koog.ai/ ◦ https://www.jetbrains.com/koog/ • 公式リポジトリ(数十のサンプル、テスト、 Androidなど) ◦ https://github.com/JetBrains/koog • 開発者の記事 ◦ https://medium.com/@vadim.briliantov • Youtube(Jetbrains/Kotlin Conf、最後の参考文献にリンクあり) • Slack Channel • Koogに限定せず、並行してLangChainやクラウド系に触れるのもあり 28
  17. LLMClient, PromptExecutor • シンプルにLLMを呼び出す ◦ Prompt API(Kotlin DSL) • PromptExecutorは複数の

    Providerを扱える ◦ 処理によって別のプロバイダーの モデルを使い分けることが可能 ◦ (※同一Provider内のモデル切り替えは LLMClientでも可能) ◦ CachedPromptExecutorは プロンプトをキャッシュしておき 同じ入力が来たときに使う 31 複数のProvider val executor = simpleOpenAIExecutor(apiKey) val prompt = prompt { system("You are a helpful assistant. Answer user questions concisely.") user("Hello! How can you help me?") } executor.execute(prompt) // Hello! How can I assist you today? val multiExecutor = MultiLLMPromptExecutor( LLMProvider.OpenAI to openAIClient, LLMProvider.Ollama to ollamaClient ) PromptExecutor
  18. 🤖 Agent • ワークフロー、ツールを使う • 数行で簡単に使える • strategyなしだとデフォルトの SingleRunStrategyになる ◦

    strategy: ワークフローを定義 するもの val agent = AIAgent( promptExecutor = simpleOpenAIExecutor(apiKey), llmModel = OpenAIModels.Chat.GPT4o ) val result = agent.run("Hello! How can you help me?") 32 エージェント val agent = AIAgent( promptExecutor = executor, strategy = customStrategy, llmModel = OpenAIModels.Chat.GPT4o toolRegistry = toolRegistry ) Custom Strategy Tool シンプルな例 CustomStrategy, Toolあり
  19. 🔧 Tool • AIエージェントが使うツールを定義 ◦ 定義済み(組込み)ツールもある ◦ Annotation based/Class based

    ◦ 後者のほうが高度な制御が可能 • LLMは使うツールとパラメータを 決定するだけ ◦ LLMから受けたパラメータをもとに アプリケーションがツールを実行する • @LLMDescriptionでToolの情報を LLMに教える @LLMDescription("Tools for controlling a switch") class SwitchTools(val switch: Switch) : ToolSet { @Tool @LLMDescription("Switches the state of the switch") fun switch( @LLMDescription("The state to set(true for on, …)") state: Boolean ) { switch.switch(state) } } 33 Toolの説明 パラメータの説明
  20. Koogの主要機能 • Structured Output(構造化出力) • History Compression • Streaming •

    Parallel • Embeddings • MCP • A2A protocol • Features: Tracing, Memory, Persistence • など 35
  21. 構造化出力 • LLMのテキスト応答を 特定のクラスにパース • 構造化しやすくするLLMへの説明 • 成功率を上げるため ◦ 例を渡す

    ◦ デフォルト値 ◦ パース用モデル ◦ リトライ回数 36 @Serializable @LLMDescription("Weather forecast for a given location") data class WeatherForecast( @property:LLMDescription("Temperature in Celsius") val temperature: Int, @property:LLMDescription("Weather conditions (e.g., sunny, cloudy, rainy)") val conditions: String ) LLMへの説明 val getWeatherForecast by nodeLLMRequestStructured<WeatherForecast>( name = "forecast-node", examples = exampleForecasts, fixingParser = StructureFixingParser( fixingModel = OpenAIModels.Chat.GPT4o, retries = 3 ) ) 例を渡す パース用モデル、リトライ回数 構造の定義 構造化実行
  22. History Compression • Agent内部の会話履歴を圧縮する • LLMの集中力⬆ トークンコスト⬇ • 圧縮戦略 ◦

    TLDR, Concept/Fact, チャンク, 最後のN個 37 val compressHistory by nodeLLMCompressHistory<ReceivedToolResult>() … edge(callLLM forwardTo executeTool onToolCall { true }) edge(executeTool forwardTo compressHistory onCondition { historyIsTooLong() }) edge(compressHistory forwardTo sendToolResult) edge(executeTool forwardTo sendToolResult onCondition { !historyIsTooLong() }) … 履歴圧縮用Node
  23. • チェックポイント ◦ エージェントの状態を保存/中断して再開 ◦ 会話履歴、状態、ワークフローの進捗を 保存 • 保存先 ◦

    InMemory, File, Custom(DB, CloudStorage) • enableAutomaticPersistence ◦ 自動保存 ◦ 任意のタイミングでの保存も可 💾 Persistence(Check Point) 38 val agent = AIAgent( promptExecutor = executor, llmModel = OllamaModels.Meta.LLAMA_3_2, ) { install(Persistence) { storage =     InMemoryPersistenceStorageProvider() enableAutomaticPersistence = true } } 自動保存 保存先
  24. Strategy • Strategy: エージェントが入力から結果を出力するまでのプロセスを表す概念 ◦ GraphStrategy, FunctionalStrategy(v0.5.0~) ◦ FunctionalStrategyはifやwhileなど普通の関数のようにロジックを記述 ▪

    Prototype用途 ▪ チェックポイントやトレースが使えない • GraphStrategy: グラフ構造でワークフローを定義 (※ここで言うワークフローは Anthropicの言うワークフローより、エージェントを含む広い範囲を含めます ) 40
  25. Graph • Node: 特定の操作 ◦ Ask LLM, Call Tool, Update

    Prompt… • Edge: Node間の関係 • 会話履歴やコンテキストは 自動で管理される 41
  26. ワークフローのDSL 42 Nodeの接続 edge(nodeStart forwardTo nodeAskLLM) edge(nodeAskLLM forwardTo nodeCallTool onToolCall

    { true }) edge(nodeAskLLM forwardTo nodeFinish onAssistantMessage { true }) edge(nodeCallTool forwardTo nodeSendToolResult) edge(nodeSendToolResult forwardTo nodeFinish onAssistantMessage { true }) edge(nodeSendToolResult forwardTo nodeCallTool onToolCall { true }) 条件分岐 条件分岐
  27. edge(nodeStart forwardTo nodeAskLLM) edge(nodeAskLLM forwardTo nodeCallTool onToolCall { true })

    edge(nodeAskLLM forwardTo nodeFinish onAssistantMessage { true }) edge(nodeCallTool forwardTo nodeSendToolResult) edge(nodeSendToolResult forwardTo nodeFinish onAssistantMessage { true }) edge(nodeSendToolResult forwardTo nodeCallTool onToolCall { true }) ワークフローのDSL 43 nodeStart then nodeAskLLM thenはedge/forwartToの シンタックスシュガー edge(someProcess forwardTo nodeFinish onCondition { it.isSuccess } transformed { it.getOrThrow().structure }) 出力変換 条件分岐
  28. • LLMの処理、それ以外の様々な処理 ◦ prompt更新、ツールの実行、ログ出力、 path-through… • 定義済みのNode ◦ nodeLLMRequest, nodeLLMRequestStructured,

    nodeLLMRequestStreaming, nodeLLMCompressHistory, nodeExecuteTool, nodeSendResult, nodeDoNothing… • or CustomNode Nodeについて 44
  29. 入出力の型 45 strategy<String, String>("single_run") { val nodeAskLLM by nodeLLMRequest() val

    nodeCallTool by nodeExecutorTool() edge(nodeStart forwardTo nodeAskLLM) edge(nodeAskLLM forwardTo nodeCallTool onToolCall { true }) … } 入力型 出力型 val nodeAskLLM by node<String, Message.Response> { input -> llm.writeSession { updatePrompt { user(input) } requestLLM() } } 入力型 出力型 Strategyの型 Nodeの型
  30. Custom Node • LLM Session: LLMと構造化された方 法で対話する概念 ◦ 排他制御で安全 ◦

    処理は短く終わる必要がある • Message型: LLMの会話の単位 ◦ System, User, Assistant, Tool ◦ LLMへのメッセージの抽象化 • updatePrompt: メッセージの追加 ◦ 全置き換えにはrewritePrompt 46 val nodeAskLLM by node<String, Message.Response> { input -> llm.writeSession { updatePrompt { user(input) } requestLLM() } } LLMSession LLM呼び出し prompt更新
  31. ワークフロー設計指針(3/3) • Strategy, SubGraph, Nodeは定義済み(組込み)のものを優先 ◦ Stretegy ▪ SingleRunStrategy/ChatStrategy/ReActStrategy ◦

    SubGraph ▪ SubGraphWithTask/SubGraphWithRetry/SubGraphWithVerification… ◦ ワークフローやプロンプトが最適化されている ◦ 多くのユースケースは定義済みのもので十分 ▪ デフォルトのSingleRunStrategyにtoolを渡すだけでもOK • 並列化: LLMの応答は時間がかかるので、並列化 51
  32. SubGraph or マルチエージェント • マルチエージェント: 複数エージェントで特定のタスクに専念させる • 会話履歴を共有するか ◦ SubGraph:

    共有する、マルチエージェント: 共有しない ◦ 以前の会話を踏まえたいか、コンテキストを限定したいか • Koogのマルチエージェント ◦ AIAgentService.createAgentToolで、Toolとして呼びだす ◦ A2A (Agent-to-Agent) protocolにも対応 ▪ (他のエージェントと通信するプロトコル ) 52
  33. 🌍 翻訳CLIツール • 翻訳までの手数を減らす • ☑ CLIツールなのでターミナルで完結、パイプ対応 • ☑ ソース言語とターゲット言語を自動で特定

    • ☑ 言語コードを覚えなくて良い • ☑ 要約機能 • ☑ モデル選択可能 • ☑ 長文対応: LLMには入力トークン長に限りがあるので対応が必要 54 https://github.com/hiroaki404/gentrans
  34. 55

  35. どう作るか(1/2) • 最もシンプルな実装: PromptExecutorでシンプルにLLM を呼び出す • 他の機能のためワークフローを定 義した 56 val

    input = "Koogは素晴らしいフレームワークです。 " val res = executor.execute( prompt = prompt("prompt") { system ("You are a helpful translator.") user("Translate this to English: ${input}") }, // model… ) println(res.last().content) // Koog is a wonderful framework. 入力 Template
  36. ワークフロー 58 nodeStart then detectSourceLanguage then decideTargetLanguage if (shouldSummary) {

    /* summaryByLLM nextChunk to TranslateByLLM to FinalizeSummary */ } else { decideTargetLanguage then translateByLLM } edge(translateByLLM forwardTo finalizeTranslation onCondition { it.inputTexts.isEmpty() }) edge(translateByLLM forwardTo translateByLLM onCondition { it.inputTexts.isNotEmpty() }) edge(finalizeTranslation forwardTo nodeFinish) 長文チャンクがなくなるまで
  37. • ローカルLLM対応 ◦ 簡単なタスクに分割 • LLMの長文翻訳のパターン ◦ Stuff, Map, Reduce,

    Refine ▪ (要約を翻訳の前後どちらでやるかのパターンもある ) ◦ LLMのタスクごとに研究されたパターン を探してみると良い • 改善点 ◦ 長文のパフォーマンスのための翻訳処理の並列化 ▪ Koogには並列化のノードがある ◦ エージェント機能(例: Androidの文字リソースの翻訳ファイル作成 ) 工夫した所/改善すべきポイント 59
  38. 旅行AIエージェント • 旅行プランを立てるエージェント • ComposeのUI(Multiplatform) • 旅行の位置情報を地図上に視覚的に表示 • 処理の流れ ◦

    1⃣ユーザーの要望を聞き出す ◦ 2⃣旅行計画を立てる ◦ 3⃣ユーザーの承諾を取ってカレンダーに登録する • 外部ツール連携(Web検索、カレンダー登録、Mapbox API) 61 https://github.com/hiroaki404/trip-ai
  39. 62

  40. どう作るか/設計したグラフ 64 🔧 WebSearch   MapTool 2⃣旅行プラン作成 TripPlanクラス にパース 1⃣要望明確化

    🔧 AskTool Human in the Loop 3⃣評価 🔧 Feedback Calendar Human in the Loop subGraphにはビルドインの subGraphWithTaskを利用
  41. サブグラフ 65 val planTrip by subgraphWithTask<String, String>( tools = webSearchTools.asTools()

    + directionsTool, ) { requestInfo -> planTripPrompt(requestInfo) } 事前定義されたSubGraph nodeBeforePlanTrip then planTrip then nodeStructuredOutput Nodeと同様に ワークフローに組み込める Tool
  42. • ツール利用を最適化するプロンプト ◦ LLMはツールを使わずに応答しがち ◦ ワークフローの中のプロンプトは、 細かく指示を出すと成功する ◦ ツール利用の義務付け、使用回数の目安 を指示

    • サブグラフに与えるツールを限定 ◦ ツールを与えすぎるとLLMが混乱する • 改善点 ◦ 他のツールを使う ▪ 天気予報、フライト予約、自社 API(ホテル予約、記事のブックマーク ...) 工夫した所/改善すべきポイント 66
  43. • 社内システム、エンタープライズアプリケーション ◦ 出張精算AI、料理レシピAI… • サーバーサイド(Ktor, Spring boot) ◦ SSE(Server-Sent

    Events)でツール呼び出しなど途中の状態を返す ◦ Streaming(LLMの応答を少しずつ返す) 応用のアイデア 67
  44. エージェントのデザインパターン • ゼロから思いつくのは難しいので先人のパターンを借りる • よく使われるパターンを使う ◦ Re-Act Human In the

    Loop, 検証, Orchestrator • Agent Design Pattern Catalogue: A Collection of Architectural Patterns for Foundation Model based Agents ◦ https://arxiv.org/abs/2405.10467 • 12-Factor Agents - Principles for building reliable LLM applications ◦ https://github.com/humanlayer/12-factor-agents • サンプルを見る ◦ Koog, LangChain, Android Developer Kit.. 68
  45. • LLMOps ◦ Langfuse, W&B Weave… ◦ 開発運用を効率化する ◦ Tracing、Playground、

    プロンプト管理、Evaluation、 Observability… • Langfuse ◦ Open Sourceでおすすめ ◦ Self Hosted(for security) 運用 71 https://langfuse.com/ プロンプト管理
  46. • エンタープライズアプリで評価は重要 • 改善したことを評価・計測する ◦ 定量的評価 ◦ 人による評価、LLM as a

    Judge ◦ LLMタスクごとの評価ベンチマーク ◦ オフライン評価/オンライン評価 ◦ エージェントの行動軌跡の評価 • 正しく評価するのは難しい ◦ ベンチマークが良くても、 ユーザー体験と結びつかないかも ◦ コストもかかる 評価 72 Claudeのオンライン評価の例 https://claude.ai/
  47. 主な参考文献/謝辞 • Koog公式(Catch Upのページも参照) https://docs.koog.ai/ https://github.com/JetBrains/koog https://www.jetbrains.com/koog/ ◦ スライドのコードは Githubを引用しています

    • Youtube(Jetbrains/Kotlin Conf) https://www.youtube.com/watch?v=O8WQCrdza8E https://www.youtube.com/watch?v=2l1GBp80CbY&t=1527s https://www.youtube.com/watch?v=AGHONAx8gjQ (他にもYoutubeで検索するとヒットします ) • LangChain/LangGraph https://www.langchain.com/ • Langfuse https://langfuse.com/ • Genkit https://genkit.dev/ • 書籍 ◦ LangChainとLangGraphによるRAG・AIエージェント(エンジニア選書) ◦ AIエージェント開発 / 運用入門 [生成AI深掘りガイド](SBクリエイティブ) Thanks • Jetbrainsの皆さん(特にKoog開発者のVadim Briliantovさん)、Kotlin Slackのさん • 「いらすとや」さんのイラスト 74