Closed14

エージェントのツール連携用フレームワーク「Composio」を試す

kun432kun432

タイトルが正しいのがちょっとわかららないけども。

https://github.com/ComposioHQ/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のブログ記事がわかりやすいかも。

https://blog.composio.dev/composio-vs-langchain/

しかし、LangChainのツールには多くの不満が残る。ツールはデモプロジェクトには適していますが、本番で何百もの顧客にサービスを提供するには、強固なセキュリティと信頼性が要求されます。そこでComposioが登場した。最適化されたツール、高度な認証管理、本番規模のデプロイメントに対する強固なサポートにより、これらのギャップを解決する包括的なソリューションを提供する。

kun432kun432

価格。一応無料枠があるので、それを使って試すことにする。環境はColaboratoryで。

https://composio.dev/pricing/

https://composio.dev/ にアクセスしてアカウントを作成、APIキーを取得する。

では、Documentにしたがって、Quick Startを進める。

https://docs.composio.dev/introduction/intro/quickstart

なお、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レポジトリにスターを付けて。

レポジトリを見るとスターが付いていた。

kun432kun432

Quick Startの一番下に"Putting it all together"でここまでのコードを全部1つにした例みたいなのがあるけど、Assitant APIを使わずに普通にChat CompletionでTool Calling使ってるように見える。最初からこっちを説明したほうがわかりやすいんではなかろうか・・・

と思ったけど、なんか最後のほうはAssitant APIのrunとかスレッドを参照していたりして、Chat CompletionとAssitant APIがごっちゃになってる気がするな、なんか間違ってるのではなかろうか。

とりあえず動いたのはわかったんだけども、もうちょっと生のやりとりがみたい感がある。

kun432kun432

Assitant APIは以前に試しては見たものの、自分的にはちゃんと理解できているとは言い難い。

https://zenn.dev/kun432/scraps/a2609d067ae036

ということで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もうまく処理してくれると嬉しいんだけどなー、どうせレスポンスを全部見ているのだし。

kun432kun432

ちなみに自分はLlamaIndexをよく使っているので、LlamaIndexでの実装も見てみる。

https://docs.composio.dev/framework/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

このデータは週ごとの追加と削除の数を示しています。
kun432kun432

ここまでの所感

  • Composioで嬉しいところ
    • ビルトインで用意されている多くのツールを簡単に組み込むことができる。
    • いちいちツールごとにモジュール組み込んで、ではなく、Composioというレイヤーがそれを全部やってくれる
    • 多くのエージェントフレームワークに対応しており、フレームワークにおいては単なるツールとして組み込むだけなので変更も少ない。
    • ツール回りで面倒な必要な認証等もやってくれる
  • あまり嬉しくないところとか確認が必要なところ
    • ツールも有料のものがある上に、さらにcomposioのプラットフォーム利用料がかかってくる
      • まあこれは致し方ない
    • Composioが提供するのはパブリックなもの。実際にはカスタムなツールのほうが必要性・重要性は高くなる気がする
      • Composio上でカスタムツールを定義することはできるみたい
    • 例えばユーザ側で認証が必要なものとかはどう組み込むのか?

とりあえず、この手のいろんなサービスへのインテグレーションは、

  • 世の中の様々なサービスに対して、どれだけ対応できるか?
  • サービス側も変更が行われる。どれだけ追随できるか?

というところがキモというか、特に後者はペインだと思うので、このあたりの面倒をお金で解決するっていうスタンスにはなると思うので、あとはその便利さがコストに見合うかどうかってところになる。

kun432kun432

Composioのコアコンセプト

Composioを理解して使うために、コンポーネントのコンセプトを見てみる。

https://docs.composio.dev/introduction/foundations/basic

  • Integration
    • ユーザーアカウントをComposioに接続するために使用されるツールの設定
      • アカウント接続時に要求するパーミッションとか
      • OAuthの場合はClientID/Secretとか
    • 独自の設定を使用することもできるし、ComposioのデフォルトのIntegrationを使用することもできる。
      • Githubインテグレーションは、リポジトリへのアクセス許可とユーザーデータを必要とする
        • APIキーを必要とするリニアなインテグレーション
        • Oauthを使用したリニアなインテグレーション
  • 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 ケース、など
kun432kun432

Integrations

https://docs.composio.dev/introduction/foundations/components/integrations/integration-guide

  • 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を設定することもできる。

kun432kun432

Entity & ConnectedAccount

https://docs.composio.dev/introduction/foundations/components/entity/entity-guide

https://docs.composio.dev/introduction/foundations/components/integrations/connected-account

ここはセットで考えるのが良さそう。

  • 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に接続してそのユーザのメールを読む、なんかはこちらにする必要があるのだと思う。

kun432kun432

Actions/Custom Actions/Tools/Custom Tools

https://docs.composio.dev/introduction/foundations/components/actions/action-guide

https://docs.composio.dev/introduction/foundations/components/actions/local-code

https://docs.composio.dev/introduction/foundations/tools/tools-intro

https://docs.composio.dev/introduction/foundations/components/integrations/custom-integration

  • 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なんかのためのツールもビルトインで用意されているっぽいね。

kun432kun432

Triggers

https://docs.composio.dev/introduction/foundations/components/triggers/trigger-guide

  • Triggers
    • あらかじめ定義された条件。
    • この条件を満たした場合にエージェントにWebhookを開始させる。
    • 例:
      • 新規のGithubのIssue
      • 新規のGithub PR
      • 新規のGithubリリース
      • 新規のHubspot チケット
      • 新規 Hubspot ケース、など

Integrations/Tools側で何かしらのアクションがあった場合にWebhookを受けてエージェントに処理をさせることができる。

kun432kun432

所感

ComposioのCLIを実行していると何が起きているのかよくわからなかったので、コンセプトやコンポーネントについては理解しておく必要がある

そのうえで、何かしらの外部ツールへの連携に必要なことは一通り抑えられていて、

  • ビルトインで用意されている多くのツールを簡単に組み込むことができる。
  • いちいちツールごとにモジュール組み込んで、ではなく、Composioというレイヤーがそれを全部やってくれる
  • 多くのエージェントフレームワークに対応しており、フレームワークにおいては単なるツールとして組み込むだけなので変更も少ない。
  • ツール回りで面倒な必要な認証等もやってくれる

改めてこの辺はメリットかなと思う。

ただ、まだまだ開発途上のようで、例えば、Composio CLIを意味わからずに適当に使ってると、ConnectedAccountはこうなる。

これ全部自分の同じアカウントなので、全く意味がない上、現状は削除ができない(ドキュメントにはあるのだけども、確認してみたらまだ削除はサポートできていないとのこと)。あと管理的にはこの辺は検索したりフィルタしたりみたいなことをEntityをキーにやりたくなると思うけど、ダッシュボードにもそういう機能はない。

なので、あくまでも現時点では、例えば自社のサービスに組み込んで使うといった場合、簡単なものなら問題なさそうだけど、細かいところは色々足りなさそうに思う。今後に期待というところかな。(LLM関連のプラットフォームなりサービスなりはこういうのが多いね、致し方ないところではある)

ドキュメントは結構充実してるのではないかなと思う、特にサンプルは豊富にあるようなので、それをいろいろ試すのが良さそう。

https://docs.composio.dev/guides/examples/Example

kun432kun432

自分一人しか使わないとかなら何も問題はないと思う。ただ無料アカウントだとカスタムは作れない。

このスクラップは4ヶ月前にクローズされました