Reachy mini を賢くする:Function Calling(Tool)の追加方法を内部構造まで踏み込んで解説
Reachy mini を賢くする:Function Calling(Tool)の追加方法を内部構造まで踏み込んで解説
CES 2026 でも話題になった Reachy mini にカスタムのToolを導入する方法をご紹介します。この記事では、公式のReachy Mini conversation appのcore_tools.py と profiles/ の仕組みを前提に、新しい Tool を追加する最短手順をまとめます。
今回使用する公式のReachy Mini conversation appリポジトリ
全体像:Reachy mini はどうやって「道具」を使うのか?
Function Calling の流れは、クライアントと OpenAI のキャッチボールです。
処理の流れ(概要)
- Client:起動時に「使える Tool 一覧」を OpenAI に渡す
- OpenAI:会話の流れから Tool 使用を決定し、Tool 実行指示(JSON)を返す
-
Client:指示を受け取り、ローカルの Python で Tool を実行する(
dispatch_tool_call) - Client:結果(JSON)を OpenAI に返す
- OpenAI:結果を踏まえ、自然言語で返答する
シーケンス図(Mermaid)
core_tools.py は何をしているのか?
Reachy mini のアプリにおいて、core_tools.py は ツール管理を担います。ツール追加が簡単に見える理由は、ここが面倒な処理を吸収しているからです。
主な役割
-
動的ロード
profiles/などをスキャンし、ツールを自動で読み込む -
スペック生成
OpenAI に渡す JSON Schema を自動生成する(get_tool_specs) -
依存性注入(Dependency Injection)
カメラ、ロボット、各種クライアントなどをToolDependenciesとして実行時に渡す
実践:新しい Tool を追加する
ここでは例として、サーバー時刻を返す server_time ツールを追加します。
Step 1:置き場所を決める
ツールの置き場所は、用途で決めます。
-
共通で使う(推奨)
reachy_mini_conversation_app/tools/server_time.py -
特定プロファイル専用
reachy_mini_conversation_app/profiles/<profile_name>/server_time.py
今回は共通ツールとして tools/ に追加します。
Step 2:コードを書く
Tool を継承して実装します。重要点は次の 2 つです。
-
parameters_schema:OpenAI に渡す 引数の定義(JSON Schema) -
async def __call__:実処理(返り値は JSON)
# reachy_mini_conversation_app/tools/server_time.py
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
from zoneinfo import ZoneInfo
from reachy_mini_conversation_app.core_tools import Tool, ToolDependencies
@dataclass
class ServerTimeTool(Tool):
# 1) ツール名と説明(AI が読む)
name: str = "server_time"
description: str = "サーバーの現在時刻を返します。"
parameters_schema: dict | None = None
def __post_init__(self) -> None:
# 2) 引数定義(JSON Schema)
if self.parameters_schema is None:
self.parameters_schema = {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "タイムゾーン(例: Asia/Tokyo, UTC)",
"default": "UTC",
},
},
"required": [],
"additionalProperties": False,
}
# 3) 実処理
async def __call__(
self,
deps: ToolDependencies,
timezone: str = "UTC",
**kwargs,
) -> dict:
try:
tz = ZoneInfo(timezone)
now = datetime.now(tz)
return {
"ok": True,
"timezone": timezone,
"iso_time": now.isoformat(),
"display_time": now.strftime("%Y-%m-%d %H:%M:%S"),
}
except Exception as e:
return {"ok": False, "error": str(e)}
Step 3:tools.txt に登録する
ファイルを作っただけでは読み込まれません。対象プロファイルの tools.txt に追記します。
- 場所:
reachy_mini_conversation_app/profiles/<profile_name>/tools.txt - 書き方:拡張子は不要
# tools.txt に追記
server_time
Step 4:再起動して確認する
アプリを再起動し、ログで server_time のロードを確認します。次に、音声またはテキストで質問します。
- 「今の時間は?」
- 「UTC の時刻を教えて」
- 「Asia/Tokyo の時刻は?」
Tool が呼ばれれば、次のような形式の JSON が返り、OpenAI が自然な文章にして返します。
{
"ok": true,
"timezone": "Asia/Tokyo",
"iso_time": "2026-01-20T21:00:00+09:00",
"display_time": "2026-01-20 21:00:00"
}
ハマりポイントと実装のコツ
additionalProperties: false は必須
parameters_schema に additionalProperties: False を入れると、OpenAI が存在しない引数を送る事故を減らします。
deps を使う前に必ず確認する
deps にはカメラやロボット操作の依存関係が入ります。ただし、状況により利用できないケースがあります。ツール内では 存在確認を入れます。
返り値は小さく保つ
Tool の返り値は、そのまま会話コンテキストに入ります。巨大なデータを返すと、動作が遅くなりコストも増えます。必要最低限の JSON を返します。
まとめ
- Reachy mini の Tool 追加は **「Tool 実装」→「tools.txt 登録」**で完了します
-
core_tools.pyが 動的ロード/スキーマ生成/依存性注入を担うため、追加コストが小さくなります - この仕組みで、天気取得、IoT 操作、社内検索などを段階的に増やせます
Happy Hacking 🤖✨
Discussion