Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.qlaud.ai/llms.txt

Use this file to discover all available pages before exploring further.

When you POST /v1/threads/:id/messages, the tools_mode field decides which subset of your registered tools the model sees for that turn. Three modes, each mapping to a different app archetype.

At a glance

ModeWhat the model seesBest for
dynamic4 meta-tools (search/get/multi-execute/manage). Model discovers + calls tools on demand, including per-user MCPs end-users connect inline.Consumer apps where end-users own their data (Notion, Stripe, GitHub, …)
tenantEvery tenant-shared tool you own, auto-attached. Built-ins, tenant-mode MCP servers, webhook tools. No meta-tools, no per-user MCPs.Company-internal agents, support bots, automation — “use OUR tools every turn”
explicitExactly the tool IDs you list in the tools field. Nothing else.Surgical control. You change the available toolset between calls.

Defaults

If you don’t set tools_mode explicitly:
  • tools field present → defaults to explicit
  • tools field absent → defaults to dynamic
You never need to set tools_mode for the common cases. Set it only when you want tenant or want to override the default.

dynamic — discover-then-call

The model receives 4 meta-tools instead of your registered ones:
  • qlaud_search_tools(intent) — keyword + embedding search across your catalog AND every per-user MCP catalog entry.
  • qlaud_get_tool_schemas(names) — fetch full input schemas for picked tools.
  • qlaud_multi_execute(calls) — fan-out execute multiple tools in one turn.
  • qlaud_manage_connections(action, tool) — bring up the per-user OAuth / paste-API-key flow inline in chat for end-users.
This is the right mode for consumer-facing apps. Token overhead stays bounded regardless of how many tools you have, and end-users self-serve their own integrations (their Notion, their Stripe, their Calendar) without you having to register anything per-user.
curl https://api.qlaud.ai/v1/threads/$THREAD_ID/messages \
  -H "Authorization: Bearer $QLAUD_KEY" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "tools_mode": "dynamic",
    "content": [{"type":"text","text":"Find any GitHub issues I'\''m mentioned in this week"}]
  }'
For the deep dive on dynamic mode (token math, meta-tool semantics, performance comparison), see tools_mode: dynamic.

tenant — auto-attach all your company tools

Every tenant-shared tool you’ve registered is sent to the model, every turn, with no setup per request:
  • All your built-ins (Resend, Linear, Twilio, Slack, GitHub, http-call wrappers — anything with an encrypted config you control).
  • Every tool from your tenant-mode MCP servers (your shared Notion workspace, your shared Linear team, etc.).
  • Every webhook tool you host.
Per-user MCPs are explicitly excluded — tenant mode never asks end-users to connect their own accounts.
curl https://api.qlaud.ai/v1/threads/$THREAD_ID/messages \
  -H "Authorization: Bearer $QLAUD_KEY" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "tools_mode": "tenant",
    "content": [{"type":"text","text":"Customer is asking for a refund. Look them up and file a Linear ticket if it'\''s a known issue."}]
  }'
Maps directly to the dashboard’s “Connect with your company’s key” section. If a tool shows up there, it’ll be in tenant mode’s auto-attach list. Register a new http-call wrapper in that section, and it’s available to the model on the next request — no code change in your app, no need to update an tools: [...] array.

When to use tenant

  • Company-internal AI agents that should ALWAYS have your tools.
  • Customer support bots where the AI should email/ticket/Slack on behalf of YOUR company.
  • Automation pipelines where end-users (if any) shouldn’t see per-user OAuth UX.
  • Wrapping internal APIs with qlaud-builtin/http-call and exposing them broadly without per-message ID enumeration.

When NOT to use tenant

  • Your end-users need to connect their own accounts (use dynamic).
  • You want to gate which tools are available per-conversation (use explicit).
  • You have 50+ tenant-shared tools and want to reduce token overhead (use dynamic — it’s bounded regardless of tool count).

Hard cap

Tenant mode loads up to 200 tenant-shared tools per request. If you exceed that, switch to dynamic (no token cost from the bloat) or to explicit with a curated subset.

explicit — exactly these IDs

You enumerate the tool IDs in the tools field. The model sees those verbatim, nothing else.
curl https://api.qlaud.ai/v1/threads/$THREAD_ID/messages \
  -H "Authorization: Bearer $QLAUD_KEY" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "tools": ["tool_a1b2c3", "tool_d4e5f6"],
    "content": [{"type":"text","text":"Use only these two tools to answer."}]
  }'
Use this when:
  • Your conversation logic decides per-message which tools the model may use (e.g. step 1 = research only, step 2 = action only).
  • You’re building a guided wizard where each step exposes one tool.
  • You’re testing a new tool in isolation before going broader.

Mixing modes across a thread

tools_mode is per-message, not per-thread. You can call message 1 with tenant to give the model your full company toolset, then message 2 with explicit: ["tool_xyz"] to constrain it. The model sees a different tool array on each call; previous tool_use blocks remain in history but no longer dispatch unless the tool is in the current request’s set.

Errors

StatusMeaning
400tools_mode is set to anything other than dynamic, tenant, or explicit.
400tools_mode: "dynamic" but you also passed tools: [...]. Drop the tools field — meta-tools handle discovery.
400tools_mode: "tenant" but you also passed tools: [...]. Drop the tools field — tenant mode auto-attaches everything.
400tools_mode: "explicit" (or default with tools) but one of the listed IDs is unknown / revoked.

See also