Setu Recipes: reusable workflows across every app.Browse templates
Setuसेतु
Documentation menu

Agent frameworks

Setu returns tool definitions in the format your model API expects. Pass format to tools.list or tools.search: openai, anthropic or raw (plain JSON Schema).

OpenAI#

TypeScript
const tools = await setu.tools.search("send a slack message", { format: "openai" });
const res = await openai.chat.completions.create({ model: "gpt-4o", messages, tools });
const msg = res.choices[0].message;
if (msg.tool_calls) {
  const out = await setu.handleToolCalls({ userId, format: "openai", toolCalls: msg.tool_calls });
  messages.push(msg, ...out); // role: "tool" messages
}

Anthropic#

TypeScript
const tools = await setu.tools.search("create a linear issue", { format: "anthropic" });
const res = await anthropic.messages.create({ model: "claude-sonnet-5-5", max_tokens: 1024, messages, tools });
const uses = res.content.filter((b) => b.type === "tool_use");
if (uses.length) {
  const results = await setu.handleToolCalls({ userId, format: "anthropic", toolCalls: uses });
  messages.push({ role: "assistant", content: res.content }, { role: "user", content: results });
}

Python#

Python
tools = setu.tools.search("create an issue", format="openai")
# ... call your model, then:
tool_messages = setu.handle_tool_calls(user_id, tool_calls)

Error handling#

handleToolCalls never throws for provider problems. A failed call becomes a tool result such as

JSON
{ "error": "INVALID_INPUT", "message": "input.title is required" }

so the model can fix the arguments and retry. If the error is CONNECTION_NEEDS_REAUTH, show the user a new connect link instead of retrying.

Keep the tool list small#

Models choose better from five relevant tools than from two hundred. Use tools.search with the user's request, restrict toolkits to what the user connected, or use the MCP dynamic mode, which does this for you.