ADK x CopilotKit : useAgent でエージェントの実行と state の表示
useAgent を使うことで以下のようなことができる
ADK のエージェントの実行 (agent.runAgent())
state の取得 (agent.state)
実行状態の取得 (agent.isRunning)
ポイントは、ポイント にまとめてある
バージョン
frontend
@copilotkit/* 1.52.1
@ag-ui/client 0.0.42
backend
ag-ui-adk: 0.3.6
google-adk: 1.18.0
やってみる
CopilotKit (Next.js) と ADK のセットアップ をもとにセットアップ
agent/.env に GOOGLE_API_KEY の設定もする
エージェントの作成
agent/agents/hello.py を作成
ADK の LlmAgent と AG-UI の ADKAgent を作る
LlmAgent での、state への書き込み
以下のどちらかで、 state に保存できる
A: LlmAgent の output_key
B: tool の tool_context に明示的にセット
A: LlmAgent の output_key
output_key を使うと、session.state[{output_keyの文字列}] = 結果 のように保存してくれる。
https://adk-labs.github.io/adk-docs/ja/agents/llm-agents/#input_schema-output_schema-output_key にも書いてあった
エージェントの最終結果のテキストが session.state に保存される。エージェント間、ワークフローのステップ間でデータのやり取りをするときに使える。
code:py
from google.adk.agents import LlmAgent
hello_agent = LlmAgent(
name="hello_agent",
description="ユーザー名を state に保存するエージェント",
model="gemini-2.5-flash-lite",
instruction="""
ユーザーからの入力はでは、ユーザー名が入力されます。
ユーザー名を受け取ったら、出力として、ユーザー名を返してください。
""",
output_key="user_name",
)
B: tool の tool_context に明示的にセット
tool_context: ToolContext をシグニチャに含めることで、ADK が自動で挿入してくれる
Agent Development Kit
tool_context.state でアクセスできるため、そこに注入する
code:py
from ag_ui_adk import ADKAgent
from google.adk.agents import LlmAgent
from google.adk.tools import ToolContext
def user_name_setter(user_name: str, tool_context: ToolContext):
"""ユーザー名をセットします。"""
tool_context.state"user_name" = user_name
hello_agent = LlmAgent(
name="hello_agent",
description="ユーザー名を state に保存するエージェント",
model="gemini-2.5-flash-lite",
instruction="""
ユーザーからの入力はでは、ユーザー名が入力されます。
ユーザー名を受け取ったら、 'user_name_setter' ツールを使ってユーザー名を保存してください。
""",
tools=user_name_setter,
)
adk_hello_agent = ADKAgent(
adk_agent=hello_agent,
user_id="demo_user",
session_timeout_seconds=3600,
use_in_memory_services=True,
)
ADK と AG-UI の接続
agent/main.pyの編集
add_adk_fastapi_endpoint で追加する
code:py
from ag_ui_adk import add_adk_fastapi_endpoint
from dotenv import load_dotenv
from fastapi import FastAPI
from .agents.hello import adk_hello_agent
load_dotenv()
app = FastAPI(title="ADK Middleware Proverbs Agent")
add_adk_fastapi_endpoint(app, adk_hello_agent, path="/")
if __name__ == "__main__":
import os
import uvicorn
if not os.getenv("GOOGLE_API_KEY"):
print("⚠️ Warning: GOOGLE_API_KEY environment variable not set!")
print(" Set it with: export GOOGLE_API_KEY='your-key-here'")
print(" Get a key from: https://makersuite.google.com/app/apikey")
print()
port = int(os.getenv("PORT", 8000))
uvicorn.run(app, host="0.0.0.0", port=port)
フロントエンド
ページを作る
src/app/hello/page.tsx について、画面中央に、テキストボックスと、ボタンを立て並びで表示する画面を作って。また、テキストボックスは control component にしたい
tamago324.icon こういう時にサクッと、画面を書いてもらえるのは助かる!
src/app/hello/page.tsx を作る
useAgent を使って、エージェントの起動、state の取得をしていく
ADK のエージェントの実行 (agent.runAgent())
state の取得 (agent.state)
実行状態の取得 (agent.isRunning)
src/app/hello/page.tsx
code:tsx
"use client";
import { useAgent } from "@copilotkit/react-core/v2";
import { randomUUID } from "crypto";
import { useState } from "react";
export default function HelloPage() {
const value, setValue = useState("");
const { agent } = useAgent({
agentId: "my_agent",
});
const onClick = () => {
agent.addMessage({
id: randomUUID(),
role: "user",
content: 私の名前は${value}です!,
});
agent.runAgent();
};
return (
<div className="flex min-h-screen items-center justify-center">
<div className="flex flex-col gap-4">
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
className="rounded border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="テキストを入力"
/>
<button
type="button"
className="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
onClick={onClick}
送信
</button>
<div className="mt-4 rounded border border-gray-300 bg-gray-100 p-4">
{agent.isRunning ? (
<p className="text-gray-700">エージェントが実行中...</p>
) : (
<p className="text-gray-700">
{agent.state.user_name
? エージェントの応答: ${agent.state.user_name}
: "エージェントの応答がここに表示されます"}
</p>
)}
</div>
</div>
</div>
);
}
ポイント
useAgent を使って、どのエージェントに接続するかを指定
code:ts
const { agent } = useAgent({
agentId: "my_agent",
});
agent.addMessage() でメッセージの追加
agent.runAgent() でエージェントの実行
code:ts
const onClick = () => {
agent.addMessage({
id: randomUUID(),
role: "user",
content: 私の名前は${value}です!,
});
agent.runAgent();
};
agent.isRunning で実行状況を取得
agent.state でエージェントの state を参照
code:ts
<div className="mt-4 rounded border border-gray-300 bg-gray-100 p-4">
{agent.isRunning ? (
<p className="text-gray-700">エージェントが実行中...</p>
) : (
<p className="text-gray-700">
{agent.state.user_name
? エージェントの応答: ${agent.state.user_name}
: "エージェントの応答がここに表示されます"}
</p>
)}
</div>
実行してみる
$ pnpm dev
http://localhost:3000/hello にアクセス
テキストボックスに名前を入力して、送信
https://gyazo.com/ffd328cfe20676c5c6e0c86e116a765b
素敵!!
tamago324.icon これで、フロントエンドから、エージェントを実行して、その状態を表示できるようになった!!
参考
useAgent
コード
https://github.com/tamago324/sandbox-adk-state-copilot-0301