エージェントのツール連携用フレームワーク「Composio」を試す
タイトルが正しいのがちょっとわかららないけども。
Composio
AIエージェントのためのProduction Readyなツールセット
1行のコードで認証、精度、信頼性を心配することなく、高品質のツールと統合をエージェントに装備する!
なぜComposioなのか?
私たちは、AIベースのエージェント/ワークフローが未来だと信じている。Composioは、AIエージェントを最高のエージェント・ツールに統合し、タスク達成のために使用するための最高のツールセットである。
主な機能
100以上のツール: 様々なカテゴリーをサポート
- ソフトウェア: GitHub、Notion、Linear、Gmail、Slack、Hubspot、Salesforce、その他90のソフトウエアで何でもできる。
- OS: どこでもクリック、何でも入力、クリップボードにコピー、その他。
- ブラウザ: スマート検索、スクリーンショット撮影、MultiOn、ダウンロード、アップロード、その他。
- 検索: Google検索、Perplexity検索、Tavily、Exaなど。
- SWE: Ngrok、データベース、Redis、Vercel、Gitなど。
- RAG: Agentic RAGであらゆる種類のデータをオンザフライで処理!
- フレームワーク: OpenAI、Claude、LlamaIndex、Langchain、CrewAI、Autogen、Gemini、Julep、Lyzrなどのエージェントフレームワークのツールを1行のコードで使用できる。
マネージド認証: 6つの異なる認証プロトコルをサポートする。Access Token、Refresh token、OAuth、API Keys、JWTなどが抽象化されているので、エージェントの構築に集中できる。
精度: より良いツール設計により、ツール呼び出しにおけるエージェントの精度が最大40%向上する。
埋め込み可能: アプリケーションのバックエンドで、すべてのユーザとエージェントの認証と統合を管理し、一貫したエクスペリエンスを維持する。
プラグイン可能: 追加のツール、フレームワーク、認証プロトコルで簡単に拡張できるように設計されている。
Composioのブログ記事がわかりやすいかも。
しかし、LangChainのツールには多くの不満が残る。ツールはデモプロジェクトには適していますが、本番で何百もの顧客にサービスを提供するには、強固なセキュリティと信頼性が要求されます。そこでComposioが登場した。最適化されたツール、高度な認証管理、本番規模のデプロイメントに対する強固なサポートにより、これらのギャップを解決する包括的なソリューションを提供する。
価格。一応無料枠があるので、それを使って試すことにする。環境はColaboratoryで。
https://composio.dev/ にアクセスしてアカウントを作成、APIキーを取得する。
では、Documentにしたがって、Quick Startを進める。
なお、Composioでは以下のフレームワークに対応している。
- OpenAI (Assitant API)
- LangChain
- LangGraph
- LlamaIndex
- Autogen
- crewAI
- Lyzr
- Julep
- Griptape
- CAMEL
- PraisonAI
それぞれのフレームワークごとに別のGetting Startedが用意されているが、Quick StartはOpenAI Assitant APIを使用するものとなっているので、まずはこれに従ってみる。なお、Quick Startのゴールは
- 以下を自然言語で行う。
- 手持ちのGitHubアカウントで認証を行う
- 特定のレポジトリにスターを付ける
というものになっている。
まず、composioのパッケージをインストール。コアパッケージと、使いたいフレームワークごとのパッケージに分かれている様子。
!pip install composio_core composio_openai
!pip freeze | egrep -i "composio|openai"
composio_core==0.3.20
composio_openai==0.3.20
openai==1.35.13
次にcomposioのCLIを使ってGitHubアカウントの認証を行う。
!composio add github
エラーになる。どうやら事前にまずcomposio側の認証を行っておく必要がある様子。
Error: User not logged in, please login using `composio login`
指示通りにログインしてみる。
!composio login
認証コード発行用URLが発行されるので、ブラウザの別タブでアクセスしてみる。
Authenticating...
> Redirecting you to the login page
> https://app.composio.dev/?cliKey=XXXXXXXXXXXXXXX
> Enter authentication code:
認証コードが発行されるのでこれをコピーして、
Colaboratoryに戻って入力する。
> Enter authentication code: XXXXXXXXXXXXXXX
✔ Authenticated successfully!
再度composio add github
を実行する。
!composio add github
GitHubへのOAuth認証が求められるので、こちらもURLにアクセスして認証を行う。
> Adding integration: Github...
Please authenticate github in the browser and come back here. URL: https://github.com/login/oauth/authorize?client_id=XXXXXXXXXXXXXXXX
⣾ ⚠ Waiting for github authentication...
GitHubへの認証が完了。
✔ github added successfully!
ではOpenAI Assiant API+Composioを使って、コードを書いていく。
まず、OpenAIクライアントとComposioのツールセットの初期化。それぞれ環境変数でセットしてもよい。
import os
from google.colab import userdata
from openai import OpenAI
from composio_openai import ComposioToolSet, App, Action
openai_client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
composio_toolset = ComposioToolSet(api_key=userdata.get('COMPOSIO_API_KEY'))
Composioのツールセットから、GitHubのレポジトリにスターを付けるアクションを呼び出して定義する。
actions = composio_toolset.get_actions(actions=[Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER])
MetadataFileNotFound: Metadata file for `GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER` not found, Please run `composio apps update` to fix this
エラーになる。。。どうもアクションごとのメタデータが必要になるらしい。指示通りcomposioコマンドを実行する。
!composio apps update
⚠️ Apps does not require update
✔ Tags updated
⚠️ Actions does not require update
⚠️ Triggers does not require update
アップデートされたのかな?再度アクションを定義し直してみると今度はエラーが出なかったので問題ないみたい。
actions = composio_toolset.get_actions(actions=[Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER])
なお、このアクションはOpenAIのTool Callの定義になっている。
import json
print(json.dumps(actions, ensure_ascii=False, indent=2))
[
{
"type": "function",
"function": {
"name": "github_activity_star_repo_for_authenticated_user",
"description": "Note that you'll need to set `Content-Length` to zero when calling out to this endpoint. For more information, see \"[HTTP method](https://docs.github.com/rest/guides/getting-started-with-the-rest-api#http-method).\"",
"parameters": {
"properties": {
"owner": {
"description": "The account owner of the repository. The name is not case sensitive.",
"title": "Owner",
"type": "string"
},
"repo": {
"description": "The name of the repository without the `.git` extension. The name is not case sensitive.",
"title": "Repo",
"type": "string"
}
},
"title": "activity_star_repo_for_authenticated_userRequest",
"type": "object",
"required": [
"owner",
"repo"
]
}
}
}
]
Assistant APIのアシスタント、スレッド、メッセージを定義して、実行。
# アシスタントの作成
assistant = openai_client.beta.assistants.create(
name="パーソナルアシスタント",
instructions="あなたは親切な日本語のアシスタントです。",
model="gpt-4o",
tools=actions,
)
# スレッドの作成
thread = openai_client.beta.threads.create()
# スレッドへのメッセージ追加
message = openai_client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="GitHubのkun432/kun432レポジトリにスターを付けて。"
)
# runオブジェクトを作成
run = openai_client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id
)
Assitant APIの場合、通常はcreate_and_poll
を使ってアシスタントからの処理の完了をポーリングするのだけど、composioにはこのポーリングをラップしつつツール応答が返されたらツール実行を行うメソッドがある。
response_after_tool_calls = composio_toolset.wait_and_handle_assistant_tool_calls(
client=openai_client,
run=run,
thread=thread,
)
print(response_after_tool_calls)
Run(id='run_BHtwqwd8bKqdQF2Ff9yul1yj', assistant_id='asst_8VndcUHGW5nq6oWUkBt7MMsc', cancelled_at=None, completed_at=1720987583, created_at=1720987524, expires_at=None, failed_at=None, incomplete_details=None, instructions='あなたは親切な日本語のアシスタントです。', last_error=None, max_completion_tokens=None, max_prompt_tokens=None, metadata={}, model='gpt-4o', object='thread.run', parallel_tool_calls=True, required_action=None, response_format='auto', started_at=1720987582, status='completed', thread_id='thread_9AbmPZWUK88fiFJdgMFcK8XF', tool_choice='auto', tools=[FunctionTool(function=FunctionDefinition(name='github_activity_star_repo_for_authenticated_user', description='Note that you\'ll need to set `Content-Length` to zero when calling out to this endpoint. For more information, see "[HTTP method](https://docs.github.com/rest/guides/getting-started-with-the-rest-api#http-method)."', parameters={'properties': {'owner': {'description': 'The account owner of the repository. The name is not case sensitive.', 'title': 'Owner', 'type': 'string'}, 'repo': {'description': 'The name of the repository without the `.git` extension. The name is not case sensitive.', 'title': 'Repo', 'type': 'string'}}, 'title': 'activity_star_repo_for_authenticated_userRequest', 'type': 'object', 'required': ['owner', 'repo']}), type='function')], truncation_strategy=TruncationStrategy(type='auto', last_messages=None), usage=Usage(completion_tokens=45, prompt_tokens=833, total_tokens=878), temperature=1.0, top_p=1.0, tool_resources={})
んー、これは出来たということを言っているのかな?status='completed'
になっているようだけど。スレッドのメッセージを見てみる。
messages = openai_client.beta.threads.messages.list(thread_id=thread.id)
for message in messages.data:
print("{}: {}".format(message.role, message.content[0].text.value))
assistant: kun432/kun432レポジトリにスターを付けました。
user: GitHubのkun432/kun432レポジトリにスターを付けて。
レポジトリを見るとスターが付いていた。
Quick Startの一番下に"Putting it all together"でここまでのコードを全部1つにした例みたいなのがあるけど、Assitant APIを使わずに普通にChat CompletionでTool Calling使ってるように見える。最初からこっちを説明したほうがわかりやすいんではなかろうか・・・
と思ったけど、なんか最後のほうはAssitant APIのrunとかスレッドを参照していたりして、Chat CompletionとAssitant APIがごっちゃになってる気がするな、なんか間違ってるのではなかろうか。
とりあえず動いたのはわかったんだけども、もうちょっと生のやりとりがみたい感がある。
Assitant APIは以前に試しては見たものの、自分的にはちゃんと理解できているとは言い難い。
ということでChat CompletionでComposioを使うコードを書いてみる。まずはComposioのツールのレスポンスを見てみる。Assistant APIの場合はwait_and_handle_assistant_tool_calls
を使っていたが、シンプルにtool callレスポンスを受けて処理を行うhandle_tool_calls
というメソッドが使えそう。
import os
from google.colab import userdata
from openai import OpenAI
from composio_openai import ComposioToolSet, App, Action
openai_client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
composio_toolset = ComposioToolSet(api_key=userdata.get('COMPOSIO_API_KEY'))
actions = composio_toolset.get_actions(actions=[Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER])
messages=[
{"role": "system", "content": "あなたは親切な日本語のアシスタントです。"},
{"role": "user", "content": "GitHubのkun432/kun432にスターを付けて。"}
]
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=actions,
)
まずモデルからのレスポンスの中身。tool_call部分だけ抜粋。
print(json.dumps(response.to_dict()["choices"][0]["message"]["tool_calls"], ensure_ascii=False, indent=2))
[
{
"id": "call_zW96CkXe6fEbsQDNCRpmzts7",
"function": {
"arguments": "{\"owner\":\"kun432\",\"repo\":\"kun432\"}",
"name": "github_activity_star_repo_for_authenticated_user"
},
"type": "function"
}
]
handle_tool_calls
メソッドは、Chat Completionレスポンスをまるっと受けてツール実行を行える様子。
result = composio_toolset.handle_tool_calls(response=response)
print(result)
[{'execution_details': {'executed': True}, 'response_data': ''}]
事前にスターを外しておいたので、今回もちゃんとスターが付いていることは確認できた。
ただTool Callを使ってモデルからのレスポンスを取得するには、Tool CallのIDを付与して、ツール実行結果を返さないといけないし、今回のような実行「できた・できなかった」だけだと、いまいちモデルが正しく理解できたのかを確認するにはわかりにくい。
ということで、レポジトリのコミット頻度(週)を取得するGITHUB_REPO_S_GET_CODE_FREQUENCY_STATS
アクションに変えてみる。
actions = composio_toolset.get_actions(actions=[Action.GITHUB_REPO_S_GET_CODE_FREQUENCY_STATS])
messages=[
{"role": "system", "content": "あなたは親切な日本語のアシスタントです。"},
{"role": "user", "content": "GitHubのkun432/kun432のコミット頻度を教えて"}
]
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=actions,
)
result = composio_toolset.handle_tool_calls(response=response)
print(json.dumps(result, indent=2))
[
{
"execution_details": {
"executed": true
},
"response_data": [
[
1707004800,
116,
-18
],
[
1707609600,
32,
-18
],
[
1708214400,
3,
-3
],
[
1708819200,
4,
-4
],
[
1709424000,
9,
-9
],
[
1710028800,
10,
-10
],
[
1710633600,
7,
-7
],
[
1711238400,
6,
-6
],
[
1711843200,
5,
-5
],
[
1712448000,
5,
-5
],
[
1713052800,
11,
-9
],
[
1713657600,
11,
-11
],
[
1714262400,
6,
-6
],
[
1714867200,
9,
-9
],
[
1715472000,
6,
-6
],
[
1716076800,
2,
-2
],
[
1716681600,
6,
-6
],
[
1717286400,
6,
-6
],
[
1717891200,
7,
-7
],
[
1718496000,
3,
-3
],
[
1719100800,
6,
-6
],
[
1719705600,
9,
-9
],
[
1720310400,
6,
-6
],
[
1720915200,
0,
0
]
]
}
]
コミット時の追加・削除の頻度が時間とともに返されている様子。
ということで、これをメッセージに追加してモデルに再度リクエストを送ればいいはず。全部まとめるとこんな感じになる。
actions = composio_toolset.get_actions(actions=[Action.GITHUB_REPO_S_GET_CODE_FREQUENCY_STATS])
messages=[
{"role": "system", "content": "あなたは親切な日本語のアシスタントです。"},
{"role": "user", "content": "GitHubのkun432/kun432のコミット頻度を教えて"}
]
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=actions,
)
while True:
if response.choices[0].message.tool_calls:
messages.append(response.choices[0].message)
tool_calls = response.choices[0].message.tool_calls
for tool_call in tool_calls:
tool_call_id = tool_call.id
tool_name = tool_call.function.name
tool_result = composio_toolset.handle_tool_calls(response=response)
messages.append(
{
"tool_call_id": tool_call.id,
"role": "tool",
"name": tool_name,
"content": str(tool_result),
}
)
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=actions,
)
else:
break
print(response.choices[0].message.content)
kun432/kun432リポジトリの最近のコミット頻度を以下のように確認しました:
| 週 (Unix time) | 追加された行数 | 削除された行数 |
|---------------------|----------------|----------------|
| 1707004800 | 116 | -18 |
| 1707609600 | 32 | -18 |
| 1708214400 | 3 | -3 |
| 1708819200 | 4 | -4 |
| 1709424000 | 9 | -9 |
| 1710028800 | 10 | -10 |
| 1710633600 | 7 | -7 |
| 1711238400 | 6 | -6 |
| 1711843200 | 5 | -5 |
| 1712448000 | 5 | -5 |
| 1713052800 | 11 | -9 |
| 1713657600 | 11 | -11 |
| 1714262400 | 6 | -6 |
| 1714867200 | 9 | -9 |
| 1715472000 | 6 | -6 |
| 1716076800 | 2 | -2 |
| 1716681600 | 6 | -6 |
| 1717286400 | 6 | -6 |
| 1717891200 | 7 | -7 |
| 1718496000 | 3 | -3 |
| 1719100800 | 6 | -6 |
| 1719705600 | 9 | -9 |
| 1720310400 | 6 | -6 |
| 1720915200 | 0 | 0 |
このデータは、各週に追加および削除された行数を示しています。
うまくいけた模様。
理想をいうならばhandle_tool_calls
がTool CallのIDもうまく処理してくれると嬉しいんだけどなー、どうせレスポンスを全部見ているのだし。
ちなみに自分はLlamaIndexをよく使っているので、LlamaIndexでの実装も見てみる。
!pip install composio-llamaindex
!pip freeze | egrep -i "llama-|composio"
composio_core==0.3.20
composio_langchain==0.3.20
composio_llamaindex==0.3.20
llama-cloud==0.0.9
llama-index==0.10.55
llama-index-agent-openai==0.2.8
llama-index-cli==0.1.12
llama-index-core==0.10.55
llama-index-embeddings-openai==0.1.10
llama-index-indices-managed-llama-cloud==0.2.5
llama-index-legacy==0.9.48
llama-index-llms-openai==0.1.25
llama-index-multi-modal-llms-openai==0.1.7
llama-index-program-openai==0.1.6
llama-index-question-gen-openai==0.1.3
llama-index-readers-file==0.1.30
llama-index-readers-llama-parse==0.1.6
llama-parse==0.4.7
APIキーについては、今回は環境変数で指定する。これにより、Composioログインも不要になる。あと、composio add github
などはどうやら最初の一度だけ実行すればアカウントに紐づくようになっている様子で、2回目は実行する必要はない。
import os
from google.colab import userdata
os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY')
os.environ["COMPOSIO_API_KEY"] = userdata.get('COMPOSIO_API_KEY')
のだが、以下だけは必要だった。
!composio apps update
LlamaIndexでは、Composioはエージェントのツールとして定義するだけでよい。サンプルではFunctionCallingAgentWorker
をエージェントモジュールとして使っている。
from llama_index.llms.openai import OpenAI
from llama_index.core.llms import ChatMessage
from llama_index.core.agent import FunctionCallingAgentWorker
from composio_llamaindex import Action, ComposioToolSet
llm = OpenAI(model="gpt-4o")
composio_toolset = ComposioToolSet()
tools = composio_toolset.get_actions(actions=[Action.GITHUB_REPO_S_GET_CODE_FREQUENCY_STATS])
prefix_messages = [
ChatMessage(
role="system",
content=(
"あなたは、色々なツールが統合された日本語のエージェントです。依頼内容に応じて、様々なツールを活用・実行して、タスクを解決します。"
),
)
]
agent = FunctionCallingAgentWorker(
tools=tools,
llm=llm,
prefix_messages=prefix_messages,
max_function_calls=10,
allow_parallel_tool_calls=False,
verbose=True,
).as_agent()
response = agent.chat("GitHubのkun432/kun432のコミット頻度を教えて")
Added user message to memory: GitHubのkun432/kun432のコミット頻度を教えて
=== Calling Function ===
Calling function: github_repo_s_get_code_frequency_stats with args: {"owner": "kun432", "repo": "kun432"}
=== Function Output ===
{'execution_details': {'executed': True}, 'response_data': [[1707004800, 116, -18], [1707609600, 32, -18], [1708214400, 3, -3], [1708819200, 4, -4], [1709424000, 9, -9], [1710028800, 10, -10], [1710633600, 7, -7], [1711238400, 6, -6], [1711843200, 5, -5], [1712448000, 5, -5], [1713052800, 11, -9], [1713657600, 11, -11], [1714262400, 6, -6], [1714867200, 9, -9], [1715472000, 6, -6], [1716076800, 2, -2], [1716681600, 6, -6], [1717286400, 6, -6], [1717891200, 7, -7], [1718496000, 3, -3], [1719100800, 6, -6], [1719705600, 9, -9], [1720310400, 6, -6], [1720915200, 0, 0]]}
=== LLM Response ===
以下は、GitHubリポジトリ「kun432/kun432」の最近のコミット頻度(週ごとの追加行数と削除行数)です:
| 週の開始日(UNIXタイムスタンプ) | 追加行数 | 削除行数 |
|-------------------------------|--------|--------|
| 1707004800 | 116 | -18 |
| 1707609600 | 32 | -18 |
| 1708214400 | 3 | -3 |
| 1708819200 | 4 | -4 |
| 1709424000 | 9 | -9 |
| 1710028800 | 10 | -10 |
| 1710633600 | 7 | -7 |
| 1711238400 | 6 | -6 |
| 1711843200 | 5 | -5 |
| 1712448000 | 5 | -5 |
| 1713052800 | 11 | -9 |
| 1713657600 | 11 | -11 |
| 1714262400 | 6 | -6 |
| 1714867200 | 9 | -9 |
| 1715472000 | 6 | -6 |
| 1716076800 | 2 | -2 |
| 1716681600 | 6 | -6 |
| 1717286400 | 6 | -6 |
| 1717891200 | 7 | -7 |
| 1718496000 | 3 | -3 |
| 1719100800 | 6 | -6 |
| 1719705600 | 9 | -9 |
| 1720310400 | 6 | -6 |
| 1720915200 | 0 | 0 |
このデータは、各週ごとの追加行数と削除行数を示しています。
うん、単なるツールとして定義するだけで、実行部分等を意識しなくて良いので、かなり直感的。
AgentWorkerはLlamaIndexの低レベルなエージェントモジュールなので、よりハイレベルなエージェントモジュールを使うともっと短くかける。以下はOpenAIAgent
を使ってみた例。
from llama_index.llms.openai import OpenAI
from llama_index.agent.openai import OpenAIAgent
from llama_index.llms.openai import OpenAI
from composio_llamaindex import Action, ComposioToolSet
llm = OpenAI(model="gpt-4o")
composio_toolset = ComposioToolSet()
tools = composio_toolset.get_actions(actions=[Action.GITHUB_REPO_S_GET_CODE_FREQUENCY_STATS])
agent = OpenAIAgent.from_tools(tools, llm=llm, verbose=True)
response = agent.chat("GitHubのkun432/kun432のコミット頻度を教えて")
print("\n回答: ", response)
Added user message to memory: GitHubのkun432/kun432のコミット頻度を教えて
=== Calling Function ===
Calling function: github_repo_s_get_code_frequency_stats with args: {"owner":"kun432","repo":"kun432"}
Got output: {'execution_details': {'executed': True}, 'response_data': [[1707004800, 116, -18], [1707609600, 32, -18], [1708214400, 3, -3], [1708819200, 4, -4], [1709424000, 9, -9], [1710028800, 10, -10], [1710633600, 7, -7], [1711238400, 6, -6], [1711843200, 5, -5], [1712448000, 5, -5], [1713052800, 11, -9], [1713657600, 11, -11], [1714262400, 6, -6], [1714867200, 9, -9], [1715472000, 6, -6], [1716076800, 2, -2], [1716681600, 6, -6], [1717286400, 6, -6], [1717891200, 7, -7], [1718496000, 3, -3], [1719100800, 6, -6], [1719705600, 9, -9], [1720310400, 6, -6], [1720915200, 0, 0]]}
========================
回答: kun432/kun432リポジトリの最近のコミット頻度は以下の通りです(週ごと):
- 1707004800: 追加 116, 削除 18
- 1707609600: 追加 32, 削除 18
- 1708214400: 追加 3, 削除 3
- 1708819200: 追加 4, 削除 4
- 1709424000: 追加 9, 削除 9
- 1710028800: 追加 10, 削除 10
- 1710633600: 追加 7, 削除 7
- 1711238400: 追加 6, 削除 6
- 1711843200: 追加 5, 削除 5
- 1712448000: 追加 5, 削除 5
- 1713052800: 追加 11, 削除 9
- 1713657600: 追加 11, 削除 11
- 1714262400: 追加 6, 削除 6
- 1714867200: 追加 9, 削除 9
- 1715472000: 追加 6, 削除 6
- 1716076800: 追加 2, 削除 2
- 1716681600: 追加 6, 削除 6
- 1717286400: 追加 6, 削除 6
- 1717891200: 追加 7, 削除 7
- 1718496000: 追加 3, 削除 3
- 1719100800: 追加 6, 削除 6
- 1719705600: 追加 9, 削除 9
- 1720310400: 追加 6, 削除 6
- 1720915200: 追加 0, 削除 0
このデータは週ごとの追加と削除の数を示しています。
ここまでの所感
- Composioで嬉しいところ
- ビルトインで用意されている多くのツールを簡単に組み込むことができる。
- いちいちツールごとにモジュール組み込んで、ではなく、Composioというレイヤーがそれを全部やってくれる
- 多くのエージェントフレームワークに対応しており、フレームワークにおいては単なるツールとして組み込むだけなので変更も少ない。
- ツール回りで面倒な必要な認証等もやってくれる
- あまり嬉しくないところとか確認が必要なところ
- ツールも有料のものがある上に、さらにcomposioのプラットフォーム利用料がかかってくる
- まあこれは致し方ない
- Composioが提供するのはパブリックなもの。実際にはカスタムなツールのほうが必要性・重要性は高くなる気がする
- Composio上でカスタムツールを定義することはできるみたい
- 例えばユーザ側で認証が必要なものとかはどう組み込むのか?
- ツールも有料のものがある上に、さらにcomposioのプラットフォーム利用料がかかってくる
とりあえず、この手のいろんなサービスへのインテグレーションは、
- 世の中の様々なサービスに対して、どれだけ対応できるか?
- サービス側も変更が行われる。どれだけ追随できるか?
というところがキモというか、特に後者はペインだと思うので、このあたりの面倒をお金で解決するっていうスタンスにはなると思うので、あとはその便利さがコストに見合うかどうかってところになる。
Composioのコアコンセプト
Composioを理解して使うために、コンポーネントのコンセプトを見てみる。
-
Integration
- ユーザーアカウントをComposioに接続するために使用されるツールの設定。
- アカウント接続時に要求するパーミッションとか
- OAuthの場合はClientID/Secretとか
- 独自の設定を使用することもできるし、ComposioのデフォルトのIntegrationを使用することもできる。
- 例
- Githubインテグレーションは、リポジトリへのアクセス許可とユーザーデータを必要とする
- APIキーを必要とするリニアなインテグレーション
- Oauthを使用したリニアなインテグレーション
- Githubインテグレーションは、リポジトリへのアクセス許可とユーザーデータを必要とする
- ユーザーアカウントをComposioに接続するために使用されるツールの設定。
-
Entity
- 個人、エンティティ、チーム、組織など、ユーザーの総称。
- Composioは、認証を
Entity
レベルで管理する。 - 例
- Melissa、Sam(ユーザ名等)
- ABC Corp(組織名等)
-
ConnectedAccounts
- アプリとサードパーティ・プラットフォーム間の接続を表す。
- Integrationをユーザー固有のインスタンスにしたものであり、認証情報や特定の設定詳細を保存する。
- 例
- MelissaのGithubアカウント
- SamのHubspotアカウント、など。
-
Tools
- Composioを介してエージェントに統合され、利用できる様々なアプリケーションやツールを指す。
- 例
- シェルマネージャー
- Hubspot
- Github
- Slack
- などなど、他にも多数。
-
Actions
- エージェントが実行できるタスクのこと。
- 例
- Gmailでメールを送信
- Outlookでメールを送信
- Sendgridでメールを送信、など。
-
Triggers
- あらかじめ定義された条件。
- この条件を満たした場合にエージェントにWebhookを開始させる。
- 例:
- 新規のGithubのIssue
- 新規のGithub PR
- 新規のGithubリリース
- 新規のHubspot チケット
- 新規 Hubspot ケース、など
Integrations
- Integration
- ユーザーアカウントをComposioに接続するために使用されるツールの設定。
- アカウント接続時に要求するパーミッションとか
- OAuthの場合はClientID/Secretとか
- 独自の設定を使用することもできるし、ComposioのデフォルトのIntegrationを使用することもできる。
- 例
- Githubインテグレーションは、リポジトリへのアクセス許可とユーザーデータを必要とする
- APIキーを必要とするリニアなインテグレーション
- Oauthを使用したリニアなインテグレーション
- その他
- Integrationが設定されるとユーザ数無制限で自分のアカウントを接続できるようになる
-
1アプリに対して1 Toolもしくは1 Integrationとして、すべてのユーザがそれにつなげるのを推奨
- 多分アカウント単位での認証は後述するConnectedAccount+Entityで行うのだと思う。Integrationは接続するサービスの単位と認識している(例えばGitHubに複数のIntegrationsってのはまあ普通はいらないはず)。
Integrationを設定すると、ダッシュボードには以下のように表示される。以下はGitHubのIntegrationsが設定された状態。
上記はcomposio add github
で作成されたのだと思う。ちょっとややこしいのはこのコマンドで、OAuthの認証を行うことでConnectedAccountの設定もあわせて行われているのではないか?と推測しているのだけど、一旦それはおいておく。
ダッシュボードからツールのカタログを見つつIntegrationを設定することもできる。
Entity & ConnectedAccount
ここはセットで考えるのが良さそう。
Entity
- 個人、エンティティ、チーム、組織など、ユーザーの総称。
- Composioは、認証を
Entity
レベルで管理する。- 例
- Melissa、Sam(ユーザ名等)
- ABC Corp(組織名等)
ConnectedAccounts
- アプリとサードパーティ・プラットフォーム間の接続を表す。
- Integrationをユーザー固有のインスタンスにしたものであり、認証情報や特定の設定詳細を保存する。
- 例
- MelissaのGithubアカウント
- SamのHubspotアカウント、など。
実際に試してはいないので、完全に推測なのだけど、ざっと見た限りはこういうイメージ。
Entityを使わない場合
Integrationを追加してOAuth形の認証を行うとConnectedAccountが作成される。ConnectedAccountは、Integrationで使用するサービスへの接続に必要な認証情報を保持するコンポーネント。で、Entitiyを指定しない場合はdefault
というエンティティになる。
この場合、Composioを使用するアプリからすれば、どのユーザが繋いでも同じConnectedAccountを使ってそのサービスに接続される。ユーザ固有の情報がない場合はこれでも問題はないと思う。
Entityを使う場合
Entityを使うと、(単一・複数の)ConnectedAccountを1つのまとまりとして一意のキーを付与してまとめることができる。
例えばJohnがアプリを使う場合には、Johnが使っているサービスのアカウント(ConnectedAccount)を使用する、Melissaの場合はMellisaのものを使って接続するといった感じ。サービス側にユーザ固有の情報を持つもの、例えばGmailに接続してそのユーザのメールを読む、なんかはこちらにする必要があるのだと思う。
Actions/Custom Actions/Tools/Custom Tools
- Tools
- Composioを介してエージェントに統合され、利用できる様々なアプリケーションやツールを指す。
- 例
- シェルマネージャー
- Hubspot
- Github
- Slack
- などなど、他にも多数。
- Actions
- エージェントが実行できるタスクのこと。
- 例
- Gmailでメールを送信
- Outlookでメールを送信
- Sendgridでメールを送信、など。
実際にエージェントが使用するサービスがTools/Integrationsで、Toolsを使って実際に解決したいタスクがActions。
Actionsには3種類ある
- Default Actions
- Composioがビルトインで用意している各種サービス(Tools/Integrations)でできること
- Custom Actions
- Composioがビルトインで用意している各種サービス「以外」にユーザが自分で定義するもの
- Local Code/Local Actions
- ローカルシステム上で行われるアクション
- ファイルやディレクトリの処理
- ローカルでスクリプトを実行
- などなど
- ローカルシステム上で行われるアクション
ToolsとIntegrationsは基本的にほぼ同じ意味だと思うけど、アプリに組み込んで使う状態がIntegrationsになるのだと思う。
Toolsのページを見ていると、CodeInterpreterやRAGなんかのためのツールもビルトインで用意されているっぽいね。
Triggers
- Triggers
- あらかじめ定義された条件。
- この条件を満たした場合にエージェントにWebhookを開始させる。
- 例:
- 新規のGithubのIssue
- 新規のGithub PR
- 新規のGithubリリース
- 新規のHubspot チケット
- 新規 Hubspot ケース、など
Integrations/Tools側で何かしらのアクションがあった場合にWebhookを受けてエージェントに処理をさせることができる。
所感
ComposioのCLIを実行していると何が起きているのかよくわからなかったので、コンセプトやコンポーネントについては理解しておく必要がある
そのうえで、何かしらの外部ツールへの連携に必要なことは一通り抑えられていて、
- ビルトインで用意されている多くのツールを簡単に組み込むことができる。
- いちいちツールごとにモジュール組み込んで、ではなく、Composioというレイヤーがそれを全部やってくれる
- 多くのエージェントフレームワークに対応しており、フレームワークにおいては単なるツールとして組み込むだけなので変更も少ない。
- ツール回りで面倒な必要な認証等もやってくれる
改めてこの辺はメリットかなと思う。
ただ、まだまだ開発途上のようで、例えば、Composio CLIを意味わからずに適当に使ってると、ConnectedAccountはこうなる。
これ全部自分の同じアカウントなので、全く意味がない上、現状は削除ができない(ドキュメントにはあるのだけども、確認してみたらまだ削除はサポートできていないとのこと)。あと管理的にはこの辺は検索したりフィルタしたりみたいなことをEntityをキーにやりたくなると思うけど、ダッシュボードにもそういう機能はない。
なので、あくまでも現時点では、例えば自社のサービスに組み込んで使うといった場合、簡単なものなら問題なさそうだけど、細かいところは色々足りなさそうに思う。今後に期待というところかな。(LLM関連のプラットフォームなりサービスなりはこういうのが多いね、致し方ないところではある)
ドキュメントは結構充実してるのではないかなと思う、特にサンプルは豊富にあるようなので、それをいろいろ試すのが良さそう。
自分一人しか使わないとかなら何も問題はないと思う。ただ無料アカウントだとカスタムは作れない。
なるほどね、エージェントで使わなくても単体でも使える。つまり、自分のアプリに組み込む場合でも、API部分を抽象化してくれる。