
X特化のDeepResearchをCozeとDify連携で作る! ~Twitter(X) APIを使って検索とか
Grok3が発表されましたね!
凄そうだけど、Grok3使うために25ドル?払うのもなんだか。。って感じですね。
DeepSearchというものも発表されていて
あれはXの情報をガンガン使えるのでかなり強そう!ということで
CozeのXプラグインを使って無料でガンガンXの情報を取得して
その情報からDeepResearchしてみよう!というのを考えました。
考えて、今こうやって書いて、これから実際にやってみるところなので
失敗したり微妙だったらこれはお蔵入りになりますw
とりあえずCozeの方でやっていきます!
Cozeの使い方いまいちわかりづらくて難しいんですよね。。

Workspaceから、作ります!
右上の+Resourcesから、Workflowを選択
適当に名前つけて作成!

ここからです。

入力された文字を処理したりするときのために
Text Processingを入れます。
まあ、今回は何もせずそのまま流してますが、
例えば、lang:ja を追加するとかで日本語だけ指定して検索させるとか、そういう感じにできます!
次はプラグインの追加で

Xと調べて、こいつのSearch Tweetを追加します。


こんな感じに設定します。
countは取得件数なんですけど、上限が20っぽくてそれ以上やっても取得できないので、20で
queryのところに、前段階で処理したTextProcessingのoutputを入れます。
typeはLatestで新着順で検索できるはず
とりあえず一旦ここまででendに繋げて実行してみると
Twitterの検索ができてると思います。

なので、ぶっちゃけあとはこれで返して、サーバー側とかで整形させればいいのですが。。
せっかくなのでそこもCoze側でやってもらいましょう!
ここが一番よくわからなくて苦戦しましたw
SearchTweetの次にCodeを追加します。

ここで、Pythonを使って整形させます。
parameter valueのところをSearchTweetのpostにして
コードは。。もうそのまま載せます!
async def main(args:dict) -> dict:
# JSONデータの取得
data = args["params"]["input"] # 引数からJSONデータを取得
# 結果を格納するリスト
res = []
# ツイート情報が含まれているか確認
posts = data
# 各ツイートの詳細を整形
for post in posts:
tweet_info = {
"created_at000": post.get("created_at", "N/A"),
"user_name": post.get("user", {}).get("name", "N/A"),
"screen_name": post.get("user", {}).get("screen_name", "N/A"),
"text": post.get("full_text", "N/A"),
"retweet_count": post.get("retweet_count", "N/A"),
"favorite_count": post.get("favorite_count", "N/A")
}
res.append(tweet_info)
return res
とりあえずこんな感じ

なんかoutputがめっちゃあると思うので、邪魔なのは消して
bot って名前で typeは Array<String>で

あとは最後にEndに繋げて
outputをbotで
これで、検索した上でいい感じに整形して出力してくれます!
本当はここ、jsonにした方がいいんだろうな。。
あ、Codeのところが、JavaScriptになってる可能性があるので
Pythonに変えるのを忘れずに!

試しに実行してみると、ちゃんと取得できてると思います。
やっぱりlang:jaはあったほうがいいかもしれませんね。。w
しまったな、XのDeepResearchだ!って書いてしまったから
このあとどうするか考えないと。。
ただのX検索のためのワークフローで止めておけばよかったw
次は、これを組み込むために一旦チャットフローを作ります。
+ResourceからChatflow

ここはもうシンプルに
間にさっき作ったworkflowを入れて、適切にパラメータ設定するだけです。
そしたら次は、Homeに戻って、エージェントを作ります。


Homeに戻って、+ボタンからCreate agent

なんかごちゃごちゃしててわかりづらいなぁ。。
こういうの苦手ですw
ここの、Single Agent(LLM Mode)ってやつを
Single Agent(Workflow Mode)にします。
そうするとworkflowを追加するところがあるので
そこにさっき作ったchatflowを入れます。


そしたらもう、調べて欲しいこと投げたら検索してくれるはず!

うむ、いい感じ
ちょっと、一旦ここで公開しちゃいます!w
このままゆっくり書いてたら公開するのにいつまでかかるか。。
別に有料で売るわけじゃないので、都度書き足しでも問題ないですよね。
ちょいちょい書き足していくので、
完成!!ってなるまでは、たまに見にきてください!w
さて、あとは、Difyの方に移って、
このエージェントを色々なパターンで検索を走らせて、
その情報をいい感じにまとめて、要約すれば。。
それっぽくなるはず!
ということで、このエージェントを、API経由で呼び出せるようにしましょう。
公開ボタンを押して

トークンが必要なので、設定ボタンを押して
権限を設定してトークンを追加します。

権限としては
ボット管理、チャット管理、ワークフローの権限があれば大丈夫だと思います。
そしたらさっきの公開のところに戻って
APIにチェックを入れて公開すればOKです。
表示されるAPIキーはしっかりメモっておいてください!
あとはbotのIDが必要なので
https://www.coze.com/space/743401169602xx/bot/7472675580203xx
みたいになってるところの
右の方のやつがIDになるので、それも控えておいて
自分のUSERIDも欲しいので
homeに戻って、自分のプロフィール?みたいなところを開いて
@user319915xx
ってなってるところの
3199〜の数字がuseridです。
あとはこれを外部から呼び出すには
例えばphpだと
<?php
// APIエンドポイントURL
$url = 'https://api.coze.com/v3/chat';
$authToken = 'pat_e1eQHQAxxxx';
// リクエストデータ
$data = [
"bot_id" => "74726755xxxx",
"user_id" => "319xxx",
"stream" => true,
"auto_save_history" => true,
"additional_messages" => [
[
"role" => "user",
"content" => $_GET["s"],
"content_type" => "text"
]
]
];
// cURLの初期化
$ch = curl_init($url);
// オプションの設定
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $authToken,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
// リクエストの実行とレスポンスの取得
$response = curl_exec($ch);
// エラーチェック
if ($response === false) {
echo 'Error: ' . curl_error($ch);
curl_close($ch);
exit();
}
curl_close($ch);
// レスポンス全体を表示して確認
echo "Raw Response: " . $response . "<br><br>";
こんな感じに、ワードを投げれば検索して返してくれます!
こいつをdifyとかに組み込めば良さそうですね。
Difyでチャットフローを作成します。
コードを追加して
pythonのコードを書きます。
import json
import requests
import sys
import codecs
def main(s: str) -> dict:
url = 'https://api.coze.com/v3/chat'
authToken = 'pat_e1eQHxxxx'
data = {
"bot_id": "7472675xxx",
"user_id": "3199xxxx",
"stream": True,
"auto_save_history": True,
"additional_messages": [
{
"role": "user",
"content": s,
"content_type": "text"
}
]
}
headers = {
'Authorization': 'Bearer ' + authToken,
'Content-Type': 'application/json'
}
try:
response = requests.post(url, headers=headers, json=data, stream=True)
response.raise_for_status()
decoder = codecs.getincrementaldecoder('utf-8')()
decoded_response = ""
for chunk in response.iter_content(chunk_size=1024):
decoded_response += decoder.decode(chunk)
# ループ終了後に、残った部分をフラッシュ
decoded_response += decoder.decode(b'', final=True)
return {'result': decoded_response}
except requests.exceptions.RequestException as e:
error_message = f"Request failed: {e}"
return {'result': error_message}
if __name__ == '__main__':
if len(sys.argv) > 1:
input_string = sys.argv[1]
result = main(input_string)
print(result)
else:
print("Please provide an input string as a command-line argument.")
tokenとbotのidとuserのidはそれぞれ自分の環境に合わせてください。
これでdifyを実行すると。。

ちゃんと取れてると思います!
引き続き追記していきますが。。思ったよりも大変すぎたので、
もし読んでいただいて少しでも参考になったら、スキ?押していただけるとモチベーションになります!お願いします!