Agent recipe
Monitor brand mentions on the web and TikTok
Search the web and TikTok for your brand, then read the comments under the posts that mention it: a daily brand check an agent can run on its own.
Brand monitoring is a loop over the places people talk about you. This recipe covers two of them: the open web, through a web search capability, and TikTok, where it finds the videos that mention your brand and reads the comments under them. Run it daily and let the agent flag what is new or negative.
Each step lists the cheapest tools that serve it, with each one's price and health. Their input fields can differ from one source to the next, so read a tool's schema with GET /v1/tools/{id} before you call it, or hand the tools to a model as functions and let it fill them in.
Steps
Search the web for mentions
Web search · Web search
Run a web search for the brand name with words such as review, vs or alternative, and keep the results that are new since the last run.
Example input { "query": "\"Notion\" review" }No tool in the catalog serves this step right now. The rest of the recipe still runs; check back for this one.
Find TikTok videos about the brand
Video search · TikTok
Search TikTok videos by the brand name and its product names to catch the posts people are watching.
Example input { "keyword": "notion app" }No tool in the catalog serves this step right now. The rest of the recipe still runs; check back for this one.
Read the reactions
Video comments · TikTok
Pull the comments under the videos that mention the brand and let the agent sort them into praise, complaints and questions that need an answer.
Example input { "video_id": "VIDEO_ID_FROM_STEP_2" }No tool in the catalog serves this step right now. The rest of the recipe still runs; check back for this one.
Run the whole recipe
# Needs curl and jq. Step 1 is shown; repeat it with each step's query.
TOOL_ID=$(curl -s https://api.orcarouter.ai/v1/tools/discover \
-H "Authorization: Bearer $ORCAROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"q": "web search", "limit": 1}' | jq -r '.data.results[0].id')
# The inputs the tool takes
curl -s "https://api.orcarouter.ai/v1/tools/$TOOL_ID" \
-H "Authorization: Bearer $ORCAROUTER_API_KEY" | jq '.data.input_schema'
# Run it with those inputs
curl -s "https://api.orcarouter.ai/v1/tools/$TOOL_ID/run" \
-H "Authorization: Bearer $ORCAROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": {"query": "\"Notion\" review"}}'# pip install requests openai
import json
import os
import requests
from openai import OpenAI
BASE = "https://api.orcarouter.ai"
KEY = os.environ["ORCAROUTER_API_KEY"]
HEADERS = {"Authorization": f"Bearer {KEY}"}
# One discover query per step of the recipe.
STEPS = ["web search", "tiktok video search", "tiktok video comments"]
TASK = (
"Find this week's mentions of Notion on the web and on TikTok, "
"and summarise what people say about it."
)
def discover(query, limit=2):
r = requests.post(f"{BASE}/v1/tools/discover", json={"q": query, "limit": limit}, headers=HEADERS, timeout=30)
r.raise_for_status()
return [tool["id"] for tool in r.json()["data"]["results"]]
def run(name, tool_input):
r = requests.post(f"{BASE}/v1/tools/{name}/run", json={"input": tool_input}, headers=HEADERS, timeout=120)
return r.text # the tool's answer, or its error, goes back to the model
ids = [tool_id for query in STEPS for tool_id in discover(query)]
fns = requests.get(
f"{BASE}/v1/tools/functions",
params={"ids": ",".join(ids), "format": "openai"},
headers=HEADERS,
timeout=30,
)
fns.raise_for_status()
tools = fns.json()["data"]["tools"]
llm = OpenAI(base_url=f"{BASE}/v1", api_key=KEY)
messages = [{"role": "user", "content": TASK}]
for _ in range(10):
msg = llm.chat.completions.create(model="openai/gpt-5-mini", messages=messages, tools=tools).choices[0].message
messages.append(msg)
if not msg.tool_calls:
print(msg.content)
break
for call in msg.tool_calls:
result = run(call.function.name, json.loads(call.function.arguments or "{}"))
messages.append({"role": "tool", "tool_call_id": call.id, "content": result})// npm install openai
import OpenAI from "openai";
import type { ChatCompletionMessageParam } from "openai/resources/chat/completions";
const BASE = "https://api.orcarouter.ai";
const KEY = process.env.ORCAROUTER_API_KEY!;
const headers = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };
// One discover query per step of the recipe.
const STEPS = ["web search", "tiktok video search", "tiktok video comments"];
const TASK =
"Find this week's mentions of Notion on the web and on TikTok, " +
"and summarise what people say about it.";
async function discover(q: string, limit = 2): Promise<string[]> {
const res = await fetch(`${BASE}/v1/tools/discover`, {
method: "POST",
headers,
body: JSON.stringify({ q, limit }),
});
if (!res.ok) throw new Error(`discover: HTTP ${res.status}`);
const { data } = await res.json();
return data.results.map((tool: { id: string }) => tool.id);
}
async function run(name: string, input: unknown): Promise<string> {
const res = await fetch(`${BASE}/v1/tools/${name}/run`, {
method: "POST",
headers,
body: JSON.stringify({ input }),
});
return res.text(); // the tool's answer, or its error, goes back to the model
}
async function main() {
const ids = (await Promise.all(STEPS.map((q) => discover(q)))).flat();
const fns = await fetch(
`${BASE}/v1/tools/functions?format=openai&ids=${encodeURIComponent(ids.join(","))}`,
{ headers },
);
if (!fns.ok) throw new Error(`functions: HTTP ${fns.status}`);
const { data } = await fns.json();
const llm = new OpenAI({ baseURL: `${BASE}/v1`, apiKey: KEY });
const messages: ChatCompletionMessageParam[] = [{ role: "user", content: TASK }];
for (let turn = 0; turn < 10; turn++) {
const reply = await llm.chat.completions.create({ model: "openai/gpt-5-mini", messages, tools: data.tools });
const msg = reply.choices[0].message;
messages.push(msg);
if (!msg.tool_calls?.length) {
console.log(msg.content);
return;
}
for (const call of msg.tool_calls) {
const fn = call.type === "function" ? call.function : undefined;
const result = fn ? await run(fn.name, JSON.parse(fn.arguments || "{}")) : "unsupported tool call";
messages.push({ role: "tool", tool_call_id: call.id, content: result });
}
}
}
main();More recipes
- Track competitor TikTok accountsPull each competitor's TikTok profile, find its latest videos and read what viewers say, in three tool calls an agent can repeat every week.
- Enrich a lead listTurn a list of company domains into firmographics, a contact's work email and a recent news hook, with one API key.
- Find contact emails for a list of domainsGo from a bare domain to the right person's work email: confirm the company, find who holds the role and look up the address.
