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
"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:
# 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
)
# task default
task = client.tasks.create(agent_id=bot.id, instructions="weekly summary",
enable_history=False) # 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)
client.agents.update(bot.id, enable_task_setup_tools=None) # None resets to platform defaultHow 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 Company Agent.
- 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):
# 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",
)
# 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)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).
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 and Value & ROI.
API note:
teammate_idis the wire name for the agent id in JSON bodies, and tool names likelist_teammateskeep it too. The SDK acceptsagent_id(canonical) andteammate_idalike.
Tool reference
Older current-only tool names still work for compatibility; the canonical surface is below.
Read and inspect
Create and manage: tasks, schedules, agents, integrations
Status and access changes
These carry the irreversible or trust-sensitive operations. They ask in approval/plan mode unless the owner has granted Always-allow; autonomous/yolo supplies a standing grant. Explicit denials still apply.
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.
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:
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",
)
# 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:
run = client.runs.create_and_wait(
agent_id=1,
message="run this task whenever a new issue is opened in acme/app",
)
# 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"})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:
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