Built-in tools

Every agent gets built-in tools from the platform (no integration to connect): memory, cross-run history, self-management, and more.

Do not put them in the tools array. That array is for 3rd-party integrations and custom tools; a built-in name like "memory" returns 422. Toggle the four configurable built-ins with enable_* fields; the rest follow account and agent config.

The catalog

ToolWhat it doesConfigurableMulti-tenant
memorySave and recall per-user memories injected into contextYesYes
task historyRead previous agents, tasks, and run outputsYesYes
task setupSame-scope management of agents, tasks, runs, schedules, inboxes, and app connections (see Task setup)YesYes
feedbackInternal issue-reporting tool (report_issue)YesYes
judgmentsEvidence checks and bounded second opinions with jev_verify and jev_decide (see Jev judgments)NoYes
lessonsAppend-only self-improvement notes per taskNoYes
run deliveryDeclare how a scheduled outcome reaches the owner (set_run_delivery: email, slack, or none)YesYes
computer useA full Linux desktop: computer, bash, file editor (see Computer use)NoYes
email your ownerAgent-initiated email to the account ownerNoFirst-party only
Slack DM your ownerAgent-initiated Slack DM to the account ownerNoFirst-party only
companyCreate and manage other agents (Lead mate only)NoFirst-party only
custom toolsAgent can persist a REST, remote MCP, or Python script tool mid-runNoFirst-party only

"Multi-tenant" means the tool is available on end-user (user_id-scoped) runs. First-party only tools act on the account owner, so they are never mounted on a multi-tenant run.

The four configurable toggles

memory, history, task_setup_tools, and feedback can be set at three levels. They resolve run → task → agent → platform default (on); the most specific wins, and an omitted toggle inherits the next level up:

Python
# agent default: applies to all its runs (scheduled, webhook, inbound)
bot = client.agents.create(
    name="report bot",
    instructions="Generate read-only reports",
    enable_task_setup_tools=False,  # this persona never manages tasks
    user_id="customer_42",
)

# task default
task = client.tasks.create(agent_id=bot.id, instructions="weekly summary",
                           enable_history=False, user_id="customer_42")  # this task ignores prior runs

# run override
run = client.runs.create(agent_id=bot.id, message="One-off analysis, don't save anything",
                         memory=False, stream=False, user_id="customer_42")

client.agents.update(bot.id, enable_task_setup_tools=None, user_id="customer_42")  # None resets to platform default
How the non-configurable tools are gated
  • email your owner is always available on first-party runs; Slack DM your owner turns on when a Slack workspace is connected. Both are off on multi-tenant (user_id) runs.
  • company is mounted only for the Lead mate.
  • read-only inbox follows the agent's fetchmail setting (agents.enable_fetchmail / disable_fetchmail); SMS appears once you provision a Twilio number; computer use follows account-level sandbox execution.

Use discovery to see each tool's resolved enabled state for a given agent or end-user.

Run delivery (set_run_delivery)

On scheduled and webhook-triggered runs, agents call set_run_delivery before the closing message to declare channel: email (deep work + optional completion email), slack (quick nudge; email suppressed; first-party only for the Slack send), or none (all clear). Read the result from GET /runs/{id}/outcome (delivery_channel) or run.completed webhooks. See Runs: scheduled delivery.

Disable with disabled_builtin_tools: ["delivery"].

Task setup

Task setup tools let an agent manage work in its own scope mid-run: create tasks, set schedules, start and cancel runs, answer other runs' approval prompts, connect integrations, rotate webhooks, and write memories. On by default; disable per run with task_setup_tools=False (feedback=False works the same way):

Python
# on by default: the agent can wire its own schedule
run = client.runs.create_and_wait(
    agent_id=1,
    message="set a schedule to run every weekday at 9am UTC, then stop",
    user_id="customer_42",
)
# agent called set_task_schedule with cron="0 9 * * 1-5"

# off for runs that should not touch config
run = client.runs.create(agent_id=1, message="summarize my emails",
                         task_setup_tools=False, stream=False, user_id="customer_42")

Task setup tools act within the same account and same end-user scope: an agent can manage other agents, tasks, and runs in that scope, but never cross into a different end-user scope (Users).

Tool groupApproval rule
Most toolsFollow the run's permission mode
add_integration and current-scope aliases; set_task_schedule_active / pause_or_resume_scheduleAuto-approved routine setup; explicit denials still apply
set_task_status, set_teammate_status, set_allowed_email_sendersAsk in Auto or Plan mode unless Always-allowed; autonomous/yolo is a standing grant
decide_value_observationFresh human decision every time; cannot use “Always allow”

Attaching an app requires an active connection in the same account and end-user scope. Connecting new credentials has its own approval or consent flow. Schedule pause/resume is reversible, like setting the cadence.

The SDK's built-in Monitor tool also auto-approves like Bash; credential and protected-config blocks still apply. These setup and background-command tools count as writes for retry safety.

When a tool requires approval, unattended calls email the owner and pause. See Human-in-the-Loop.

API note: teammate_id is the wire name for the agent id in JSON bodies, and tool names like list_teammates keep it too. The SDK accepts agent_id (canonical) and teammate_id alike.

Tool reference

Older current-only tool names still work for compatibility; the canonical surface is below.

Read and inspect
ToolWhat it does
list_teammatesList agents in the current scope
list_tasksList tasks for the current or a targeted agent
list_runsInspect active or historical runs across agents and tasks in scope
get_run_detailsDrill into a run's output, messages, pending approvals, and file metadata
read_run_file_previewPreview text-like files created during another run
search_memoryKeyword-search saved memories (account-wide + this agent)
search_documentsKeyword-search visible documents; read_document opens the full text
list_task_triggersList every trigger on a task (schedule, webhook, email inbox, Composio app)
list_recent_trigger_eventsList a task's recent trigger firings and the run each produced
get_integration_connection_healthList connected integrations with status, expiry, and app-trigger support
get_run_diagnosticsInspect a run's stop reason, error, originating trigger, and webhook delivery failures

These are agent-facing MCP calls. Lists return compact summaries; request a specific item when the full content is needed:

  • list_tasks previews instructions at 200 characters and reports instructions_truncated. Pass task_id with include_instructions=True for the complete instructions.
  • list_custom_tools returns inventory metadata. Pass an exact slug or name as tool with include_definitions=True to retrieve that tool's definitions.
  • On shared-mate history, get_run_details defaults to 10 messages and 2,000 characters per message. Follow next_before_sequence using before_sequence for older messages. For a long message, pass its sequence as message_sequence and its next_content_offset as content_offset to read the next chunk.
  • The Lead mate's list_value_use_cases and list_value_observations return items, has_more, and next_cursor, with 20 rows by default. Pass next_cursor as starting_after for another page. Full details require include_details=True plus an exact use_case_id or observation_id, respectively.
Create and manage: tasks, schedules, agents, integrations
ToolWhat it does
create_taskCreate a task for the current agent or an explicit agent
update_taskEdit reversible task fields (name, instructions, content)
set_task_scheduleCreate, replace, or edit a task schedule
set_task_schedule_activePause or resume an existing schedule; auto-approved
start_task_runStart a saved task in the background
send_message_to_runQueue a message to another agent's run (same scope)
cancel_runCancel an active same-scope run
update_teammateEdit agent fields (name, role, instructions, goals) and toggle its email inbox
get_or_create_teammate_email_inboxEnable or return an agent inbox address
get_or_create_task_webhookGet the task's webhook trigger URL, creating one if it has none (never rotates; needs your approval to create)
add_integrationAttach an already-connected integration to an agent, and optionally a task
respond_to_run_inputApprove or deny a pending tool call, or answer an AskUserQuestion prompt
create_or_update_outbound_webhookRegister or update a webhook endpoint for run events
rotate_outbound_webhook_secretRotate a webhook signing secret (shown once)
list_webhook_deliveriesList recent deliveries for a webhook endpoint
create_or_update_memoryWrite or update a persistent memory in the current scope
start_app_oauth_connectionStart an OAuth flow to connect an app such as Google or Slack
connect_api_key_appConnect an app that uses an API key
disconnect_appRevoke an app connection in the current account scope
Status and access changes

These carry the irreversible or trust-sensitive operations. They ask in Auto or Plan mode unless the owner has granted Always-allow; autonomous/yolo supplies a standing grant. Explicit denials still apply.

ToolWhat it does
set_task_statusEnable, disable, or archive a task
set_teammate_statusEnable, disable, or archive an agent
set_allowed_email_sendersChange who may email-trigger an agent
App triggers (Composio)

Make a task reactive: run it when a connected app emits an event (a new GitHub issue, a Stripe payment, an inbound Gmail message). The app must already be connected as a Composio integration. See Webhook Triggers for the SDK/API path to the same triggers.

ToolWhat it does
list_app_trigger_typesDiscover the event triggers a connected app supports (slug + required config)
create_app_triggerSet up a Composio trigger so an external event runs this task
set_app_trigger_activeEnable or disable an existing app trigger
delete_app_triggerRemove an app trigger
Examples: self-improving and self-wiring tasks

The agent completes work, then updates the task instructions to record its approach, so the next run skips discovery entirely:

Python
run = client.runs.create_and_wait(
    agent_id=1,
    message="pull this week's mrr from stripe and post the delta to #revenue on slack",
    user_id="customer_42",
)
# Agent completes the work, then calls update_task to save what it learned:
# update_task(instructions="... stripe mrr is in /v1/metrics?metric=mrr.
#   compare current_period_end vs previous_period_end.
#   #revenue channel id is C01ABC123.")

Or the agent wires its own Composio app trigger, so the task runs automatically on a GitHub event:

Python
run = client.runs.create_and_wait(
    agent_id=1,
    message="run this task whenever a new issue is opened in acme/app",
    user_id="customer_42",
)
# Agent calls list_app_trigger_types("github") then create_app_trigger(
#   app="github", trigger_name="GITHUB_ISSUE_ADDED_EVENT",
#   trigger_config={"owner": "acme", "repo": "app"})

Jev judgments

Jev is an advisory second-opinion tool. Jev judgments are included on every plan, Free included, at no charge: m8tes funds them by default. API customers can connect their own TypeSafe key for account-wide provider billing; the Platform always uses m8tes funding. Neither funding mode debits your m8tes balance. Availability follows the platform service setting and, for agent tools, the agent’s built-in tool configuration. The two tools use the same service as POST /api/v2/judgments and client.judgments.create(...) in the Python and TypeScript SDKs. Do not add them to the integrations tools array.

Use your own TypeSafe key

Configure your TypeSafe API key once from a trusted server with your m8tes account credentials. The connection covers every end user and agent in that account; these connection endpoints do not accept a user_id. Keep the key in server-side environment variables or a secret manager. Never put it in agent instructions, tool arguments, browser code, or judgment state/evidence.

import os
from m8tes import M8tes

client = M8tes()  # Reads M8TES_API_KEY on your server.
connection = client.judgments.configure(api_key=os.environ["TYPESAFE_API_KEY"])
print(connection.funding_source)  # customer; the key is never returned
status = client.judgments.connection()
# Explicitly return to platform funding, when available:
# client.judgments.disconnect()

These methods use PUT, GET, and DELETE /api/v2/judgments/connection. Configure and inspect return only connected, enabled, funding_source, model, and updated_at; disconnect returns HTTP 204. Connected means a key is stored, not that TypeSafe has accepted it. Configure again to rotate the key. A key TypeSafe rejects returns HTTP 403 (jev_credential_rejected); a provider failure returns HTTP 503 (jev_unavailable). Neither silently falls back to platform funding; replace the key or disconnect explicitly.

With customer funding, TypeSafe charges your TypeSafe account directly. The per-minute rate limit and input limits still apply; the platform’s daily budgets and daily call caps do not. The platform service setting can still disable judgments. The estimated cost_usd remains available for monitoring, and funding_source identifies who funds the provider call; it is not a charge against your m8tes balance. API and agent usage automatically use the account connection without changing the judgment request.

Choose a judgment

  • jev_decide compares bounded next steps, checks completion criteria, or supplies a narrow second opinion. Pass relevant state plus named Choice, Noul, or Score questions.
  • jev_verify checks individual claims against supplied evidence. Pass claims with IDs and evidence_ids, plus evidence with IDs and original text or platform source references.

Before delivering a consequential report, use verification for claims that depend on source evidence. Batch independent checks with their original excerpts; ordinary chat messages do not need a check. Use bounded second opinions where they help resolve uncertainty, and avoid repeating unchanged checks or retrying until an answer agrees with the draft.

Disable the agent tools with disabled_builtin_tools: ["judgments"]. Existing run-scope and shared-mate permission boundaries still apply.

Verification returns a Choice for each claim: supported, contradicted, or insufficient_evidence. Supply original tool results or source passages, with the surrounding context needed to interpret them. A claim without adequate evidence should lead to gathering evidence or asking for review. A confident judgment over a fabricated or incomplete source is still not a fact check of the real world.

Evidence accepts either inline text or a source reference to an accessible platform document or stored tool result. The platform resolves references within the request’s account and end-user scope. Verification coverage.provenance records the origin, source ID when present, and SHA-256 of the resolved content. This traces what Jev evaluated; it does not authenticate the source’s claims. Every provenance item reports independently_authenticated: false. Neither tool independently researches the outside world. Keep exact arithmetic, dates, source-quote existence checks, and execution in code.

from m8tes import M8tes

client = M8tes()
judgment = client.judgments.create(
    mode="verify",
    claims=[{
        "id": "savings",
        "text": "The budget change saved money without reducing conversions.",
        "evidence_ids": ["weekly_report"],
    }],
    evidence=[{
        "id": "weekly_report",
        "text": "Spend fell after the change. Conversion tracking was unavailable.",
    }],
    user_id="customer_42",
    idempotency_key="weekly-report-2026-09-21-v1",
)
print(judgment.answers["savings"])
# Fetch the exact saved answer without another Jev call or charge.
saved = client.judgments.get(judgment.id, user_id="customer_42")
assert saved.id == judgment.id
# Inspect the advisory answer; the evidence does not establish the full claim.

Use a source reference instead of inline text when the evidence already exists on the platform. For example, evidence=[{"id": "weekly_report", "source": {"type": "document", "id": document.id}}] reads that document’s stored content. Use type: "tool_result" for a persisted conversation message ID containing tool-result blocks; assistant prose and tool inputs are excluded. Supply the original user_id; inaccessible records are rejected. A source and inline text are mutually exclusive. Optional run_id attributes API usage to a run in the same account and end-user scope; agent tools receive their run context automatically.

The endpoint accepts up to 32 questions or claims per request, up to 32 evidence items, and a 128 KiB serialized input limit after source resolution. Each source is limited to 16,384 characters; oversized content is rejected rather than silently truncated. Question instructions and rubric descriptions are strings; state may be a string, object, or array. Choice accepts 2–255 named options. Noul returns P(yes), without separate confidence. Score uses an ordered array of 2–10 rubric levels and returns a probability-weighted level. Choice/Score confidence describes distribution concentration, not factual accuracy or authority to act. Evaluate any thresholds on representative cases before using them in a workflow; the tool does not automatically approve, block, or execute actions. Existing permission and approval rules remain authoritative.

Results include the provider funding_source (platform or customer), resolved model, typed answers, token usage, latency_ms, estimated provider cost_usd, and the verification rubric_version. The cost is an estimate, not a charge against your m8tes balance; customer-funded requests are billed by TypeSafe. Successful results are available through GET /api/v2/judgments/{id} or client.judgments.get(...) for 30 days. Use the same user_id as creation. After 30 days, retrieval returns HTTP 410 (result_not_retained). Settled usage metadata with known cost is retained for 90 days; unresolved or unknown-cost reservations remain for reconciliation. Accounts or runs configured for metadata-only retention do not store answers: retrieval or replay returns HTTP 410 (result_not_retained), while the same key still prevents another paid call during its 24-hour window. Raw claims, state, and evidence text are not retained in the judgment ledger.

Pass Idempotency-Key (Python idempotency_key, TypeScript idempotencyKey, or agent-tool idempotency_key) to protect a logical operation for 24 hours. Reuse the key and identical request after a lost response; a successful replay returns the same ID and original cost without another provider charge. A changed request, in-progress attempt, or unsuccessful attempt returns a conflict instead of executing again. After 24 hours, a key may start a new operation. SDK POST retries require a key. Do not repeatedly change keys to bypass failures or limits. Validation and service failures produce API/SDK errors, never a fabricated approving answer.

Discovery

List the built-in tools with their resolved state. Pass agent_id to reflect that agent's defaults, or user_id to check multi-tenant availability:

Python
for tool in client.built_in_tools.list(agent_id=bot.id).data:
    print(tool.name, tool.enabled, tool.multi_tenant_safe)

Each entry reports name, server_name, display_name, description, enabled (resolved for the requested scope), multi_tenant_safe, and configurable.

Next: Tools · Users · Memories · Computer use

Was this page helpful?