The Assistant’s toolset
The Assistant is handed a fixed set of tools at run start. There are three discovery tools, one execution tool, one knowledge tool, and the human-in-the-loop tools (one of which isrequest_credential).
The discovery tools and execution tool together form a deliberate two-step pattern: the
Assistant first narrows the catalog, then pulls the exact parameter schema for the action
it chose, then executes. The sections below document each in turn.
Tool discovery
Browse the catalog — get_available_integrations
The first discovery step returns a compact index of everything the organization could
connect, so the full portfolio fits in the agent’s context without bloating it. For tools
you get the integration name, a short description, categories, and action names only —
no per-action descriptions or parameter schemas at this step.
string
default:"all"
One of
tools, llm_providers, knowledge_providers, or all. Filters which catalog
segment is returned.string
Optional case-insensitive substring filter. It matches name, display name, description,
category, and action name. A narrow query (for example
query="slack") keeps the
response small without risking that a relevant integration is dropped — filtering is
exact-substring, not lossy truncation.get_integration_details for the parameter schema before you can configure a call.
object[]
object[]
Each entry adds a
models list of {id, display_name, max_output_tokens}. See
LLM providers.object[]
Each entry carries
name, display_name, description, and categories. See
Knowledge providers.Read an integration’s actions — get_integration_details
The second discovery step. Call it after choosing an integration to get the parameter
schemas you need to actually configure an action.
string
required
The integration name, for example
tavily, firecrawl, or github.string
Optional. Restrict the response to a single action to keep it small. An unknown action
returns
{error: "Action '<name>' not found in <integration>"}.name, a description (truncated to 300
characters), and a parameters array. Each parameter carries name, type, required,
description, and — when defined in the manifest — enum and default:
Example: get_integration_details("github", "create_issue")
{error: "Integration '<name>' not found"}. The parameter
type is one of string, integer, number, boolean, array, or object — the same
types the manifest schema defines.
See existing credentials — get_organization_credentials
The Assistant uses this to decide whether it already has a way to authenticate before it
calls an action. It returns only safe fields — never a token, key, or secret.
string
Optional. Return only credentials for this integration (for example
slack). Pass it
when the Assistant already knows which integration it needs so the response stays small.object[]
Calling a tool
execute_integration_tool
This is the only tool that performs a real action. The Assistant calls it with the
integration id and action name it discovered, plus the action parameters. It runs exactly
one action per call.
string
required
Catalog integration id, for example
github.string
required
The action/service name, for example
list_repositories.object
default:"{}"
The action parameters, matching the schema from
get_integration_details. Never
include credentials or tokens — the runtime injects them automatically from the
organization’s credential. Credential fields such as api_key, token,
access_token, bearer_token, auth_type, and auth_data are stripped from the
schema the Assistant sees, so it cannot supply them even if it tries.Return shape
execute_integration_tool always returns a dict with a status field. It does not
raise to the agent — every failure is converted to a structured status the Assistant can
react to mid-stream.
string
required
One of
ok, cancelled, needs_credential, credit_limit, or error.string
Echoes the requested integration.
string
Echoes the requested action.
object
Present when
status is ok. The raw action output (a dict, list, or string),
truncated to 8000 characters before it re-enters the agent loop. The credential and
execution envelope around the action are stripped — the Assistant sees only the bare
action result.string
Present for
needs_credential and credit_limit — a human-readable explanation the
Assistant can act on (for example, “call request_credential, then retry”).string
Present for
cancelled (the user declined an approval) and credit_limit (the stable
token credit_exhausted).string
Present when
status is error — the failure text, truncated to 500 characters.status: ok
enum
The approval gate — reads run, destructive actions pause
The Assistant applies a safety gate (not an authorization gate — your org membership already authorizes the call) before it executes. The policy differs from the AI Composer in the builder, and the difference matters: When a destructive action is gated, the Assistant raises a yes/no human-in-the-loop interrupt with a redacted preview of the parameters (secret-looking keys are masked). If you answer no, the call returnsstatus: cancelled and the action never runs.
Credential requests over human-in-the-loop
Whenexecute_integration_tool returns needs_credential, the Assistant calls
request_credential to ask you to connect the integration. This raises a credential
interrupt: the run pauses, the app renders a connect
popup, and the Assistant resumes once you finish.
request_credential
string
required
Canonical integration slug, for example
slack or google_drive. Used to resolve
OAuth and credential storage.string
required
Human-readable name shown in the popup header, for example
Slack.object[]
required
One entry per auth type you can choose. At least one is required. Each matches the
CredentialAuthOption schema below.string
Optional URL to the integration’s logo for the popup.
string
Optional. Reserved for the workflow context and not used by the Assistant (Assistant
chats are never workflow-bound).
boolean
default:"false"
When
false (the default for the Assistant), the popup shows an inline “Skip for now”
button so you can defer connecting. Set true only when the task truly cannot proceed
without the credential.object
Optional rendering hints for the app.
auth_options is a CredentialAuthOption:
string
required
One of
oauth2, api_key, bearer_token, modulex_key, custom.string
required
The button label inside the popup.
object[]
Form-field definitions for form-based auth types such as
api_key.string
The full URL the app opens to start the OAuth flow. Required when
auth_type is
oauth2 — an OAuth option without it is rejected before the interrupt fires.string[]
Optional human-readable setup steps shown beside the form or OAuth button.
boolean
default:"false"
When
true, the new credential is round-trip tested before the Assistant resumes, so an
invalid credential surfaces as a structured failure instead of sending the Assistant
down a broken path.How you respond, and how the run resumes
You answer a credential request in one of three ways, and the Assistant resumes with that result baked into the tool response:1
You connect the integration
You complete the OAuth popup or fill the form. The credential is persisted and the run
resumes with
kind: "credential_added" carrying the new credential_id,
integration_name, and auth_type. The Assistant retries the original action.2
The connection fails
The run resumes with
kind: "credential_failed" carrying an error_code — one of
oauth_denied, oauth_provider_error, invalid_credentials, network_error,
popup_closed, timeout, or unknown — plus a retryable flag. The Assistant can
try a different auth option or report the failure.3
You skip
When the request was not
required, the inline “Skip for now” button resumes the run
with kind: "skipped". The Assistant proceeds without the credential.OAuth auto-resume. When you complete an OAuth flow that the Assistant opened, the
OAuth callback resumes the chat automatically — you do not make a separate resume
call. The callback re-runs the same ownership checks and continues the run, swapping your
live stream to the new run id. See Human-in-the-loop for
the resume contract and stream handover.
BYOK vs managed credentials
Every integration call resolves to one of two kinds of credential, and the kind decides who you pay and whether the call counts against your credits.BYOK — your own credentials
You connect your own provider account (OAuth, API key, or bearer token). Usage is billed
directly by the provider with no ModuleX markup. BYOK tool calls are not
credit-limited — they are tracked for analytics only, never gated on credits.
Managed — `modulex_key`
ModuleX provides a pooled, system-managed key (
auth_type: modulex_key) so you can call
a tool without bringing your own account. Managed usage is billed in credits and is
subject to your plan’s monthly credit ceiling. On the wire the
managed provider is modulexai for tools and LLMs, and modulexdb for
managed knowledge.Credit impact of a tool call
A managed tool call is metered with a per-action soft cost:
The credit check runs only for managed (
modulex_key) credentials: if the plan’s monthly
budget is exhausted and no wallet overage is available, the call returns
status: credit_limit with reason: credit_exhausted. Plans with no monthly ceiling
(for example Enterprise) are never blocked here. See
Credits & metering and Usage gating & limits
for the full model.
The Assistant turn itself is also metered separately from the tool. Each user message
charges one run credit per turn and is admitted through the billing gate before any work
starts. That gate, and the LLM token usage it records, are documented in
Permissions & limits and
Usage gating & limits.
Errors and denials
The Assistant’s tools surface failures in two distinct places — and they look different. Tool-level results.execute_integration_tool never raises to the agent; it returns a
status. Treat needs_credential, credit_limit, cancelled, and error as normal
control flow the Assistant handles itself.
Turn-level denials. The Assistant endpoint that starts a turn is on the billing gate.
A denial there is not the {detail} shape — it is the flat DenialEnvelope:
DenialEnvelope (HTTP 402 429)
layer maps to a status: rate → 429 (with Retry-After and X-RateLimit-*
headers), quota → 403, and credit or wallet → 402. This is one of the
four error envelopes ModuleX returns, and it is emitted on the
run, Composer, Assistant, and managed-knowledge surfaces only — plain CRUD routes use the
{detail} shape. See Errors & status codes and
Rate limiting.
A worked example: list, then create
This shows the full sequence the Assistant runs to satisfy “create a GitHub issue titled ‘Bug’ in octocat/hello-world”, calling the API directly. Authenticate every request withAuthorization: Bearer mx_live_… and X-Organization-ID — see
Authentication. Owner or admin role is required for the
Assistant; the retired member role cannot use it (see
Roles & permissions).
1
Start the turn
Post the user message. The response returns the chat id, the run id, and the SSE
stream_url to open for live events. The operation is shown once below as cURL, Python,
and JavaScript.2
The Assistant discovers and reads the action
Over the stream you see the Assistant call
get_available_integrations (with
query="github") and then get_integration_details("github", "create_issue") to read
the parameter schema. These are read-only and never pause.3
The Assistant executes
The Assistant calls Had no GitHub credential existed, the result would instead be
execute_integration_tool with the action and parameters. Because
create_issue is not destructive, it runs immediately on the Assistant surface — no
approval prompt. The tool result arrives in the stream:tool_result
{"status": "needs_credential", ...}, and the Assistant would call request_credential
and pause — see the resume steps under Human-in-the-loop.Related
Human-in-the-loop
The pause-and-resume contract behind credential requests and approvals.
Integrations overview
Connect the services the Assistant calls and manage their credentials.
How the Assistant works
The agentic loop that decides when to discover, call a tool, and finish.
Permissions & limits
Who can use the Assistant and the billing and usage limits that apply.