Technical docs
Runtime Tooling For AI Teammates
Overview
Support-facing reference for the runtime tools exposed by `backend/src/components/ai/tools/mastra/ToolsProvider.ts`.
Tool sets
- Node tools (`NODE_TOOLS_LIST`): `http.http_request` and `stargate.execute_task`. This is the publish-time catalog for plain tool nodes, not the Alloy AI runtime allowlist.
- Base agent tools (`BASE_AGENT_TOOLS_LIST`): `http.http_request`, media URL helpers, `web.check_urls`, `programming.run_code`, `contact.update_contact`, `conversation.escalate_conversation`, storage tools, `skills.list`, scheduler tools, `agent.call_teammate`, and `stargate.execute_task`.
- Agent tools (`AGENT_TOOLS_LIST`): base agent tools plus `agent.run_subagent`.
- Non-system tools (`ALL_NOT_SYSTEM_TOOLS_LIST`): agent tools plus `contact.send_message` and `ally.ask`.
- Virtual tools (`VIRTUAL_TOOLS_LIST`): `web.search` only. It is added only when the selected provider exposes a native search tool.
- System-only tools (`SYSTEM_TOOLS_LIST`): `system.employee_create`, `system.employee_update`, `system.employee_get`, `system.employees_list`, `system.create_skill_or_workflow`, `system.update_skill_or_workflow`, `system.read_skill_or_workflow`, `system.workflows_list`, `system.test_skill_or_workflow`, `system.do_organization_action`, `system.list_documentation`, `system.search_documentation`, and `system.read_documentation`.
- System tools are exposed only when `organization.is_system` is true.
Eager tools vs on-demand tools
- Built-in Alloy tools now carry an `isEager` flag.
- Eager tools are exposed to the model from step `0`.
- Non-eager tools are registered on the agent but hidden until the model loads them through `tools.load_tool`.
- If the current tool set contains any non-eager built-in tools or assigned upstream MCP/OAuth toolset tools, the runtime injects `tools.load_tool` as an eager helper.
- `tools.load_tool` takes `tool_name` as the raw Alloy tool id and returns `{ success, message, data: { id } }` on success.
- After a successful `tools.load_tool` call, the loaded tool becomes active for later steps in the same run.
- Tool matching uses sanitized runtime names internally, but `tools.load_tool` still expects the original tool id string.
Current eager built-ins
- Current built-in tools explicitly marked eager in code include:
- `programming.run_code`
- `storage.list`
- `storage.search`
- `storage.stat_file`
- `storage.read_file`
- `storage.write_file`
- `storage.edit_file`
- `storage.semantic_search`
- `system.list_documentation`
- `system.search_documentation`
- `system.read_documentation`
- Dynamic `skill.*` tools are also currently created as eager tools.
Current non-eager built-ins
- Current built-in tools that are still loaded on demand include:
- `storage.read_image`
- `storage.get_temp_file_url`
- `storage.rename`
- `storage.copy`
- `storage.move`
- `stargate.execute_task`
- System tools that are not explicitly marked eager also stay behind the loader path.
- Assigned external MCP and OAuth toolset tools are also exposed through the same on-demand loader path for AI teammates.
Dynamic skill tools
- Every other non-`employee` workflow assigned to the same AI teammate is exposed as `skill.<snake_case_name>`.
- For Ally, dynamic skill tools also include skills from the canonical Ally when it is configured and the current Ally is not that canonical Ally.
- The runtime builds the tool input schema from `workflow.payload_format`.
- If a skill has no payload schema, the runtime falls back to `{}`.
- Dynamic skill tools preserve the parent runtime context, validate inherited `state` against the child workflow's `state_definition`, and enforce max workflow nesting depth.
Realtime voice naming
- Realtime voice tooling converts snake case to camel case and replaces dots with underscores.
- Example: `contact.send_message` becomes `contact_sendMessage`.
Confirmed behavior by area
Search, web, and HTTP
- `web.check_urls` performs availability checks only; it is not a content fetcher.
- `web.search` is virtual and provider-dependent.
- `http.http_request` supports runtime placeholder substitution and secret org-variable substitution.
- `http.http_request` parses JSON responses when possible and otherwise returns text content.
- `stargate.execute_task` queues an HTTP request for a private-network system through a Stargate gateway. Use it when Alloy cannot reach the system directly; use `http.http_request` for public APIs.
- `stargate.execute_task` accepts:
- `system`
- `uri`
- `method`
- optional JSON `body`
- `stargate.execute_task` waits up to `120` seconds for a gateway response.
- If the task times out, Alloy marks it as `failed` and the tool returns `success: false`.
- The current public Stargate gateway posts a JSON envelope with `ok`, `status`, `body`, and optional `error` back to Alloy.
- Because Alloy currently stores that posted payload verbatim, the tool returns the recorded response string in `data`; callers may need to parse JSON themselves.
Skills and delegation
- `skills.list` currently returns only `id`, `name`, `description`, and `type`, scoped to the current employee's workflows.
- `agent.call_teammate` runs another employee's default `employee` workflow with `{ message: query }` and waits for the result.
- `agent.run_subagent` creates a temporary child agent flow with a selected model and a subset of `BASE_AGENT_TOOLS_LIST` plus virtual search when supported.
- `agent.run_subagent` does not pass through dynamic `skill.*` tools, `ally.ask`, `contact.send_message`, or system tools.
- `ally.ask` triggers the system "Ally" employee workflow and passes the current organization and employee as target context.
Programming
- `programming.run_code` runs Python or JavaScript in a fresh E2B sandbox.
- It supports optional package installation, read-only `storage_mounts`, exposing selected organization variables through `env_variables`, saving `/outputs/*` back to Storage, and `chat_files` for chat attachments.
- `env_variables` accepts organization variable names only. The runtime injects only variables that already exist in the organization and fails the tool call if any requested name is missing.
- Code that requests `env_variables` reads them inside the sandbox from `os.environ['NAME']` in Python or `process.env.NAME` in JavaScript.
- `storage_mounts`, `outputs`, and `chat_files` are each capped at 5 items.
- Execution timeout is 60 seconds, and the sandbox is killed after each run.
- For system AI teammates, `programming.run_code` skips shared-folder access filtering for mounted storage files and saved output targets.
Contact and conversation
- `contact.update_contact` works only when the current workflow run is tied to a conversation contact.
- `contact.send_message` is a normal selectable tool in text mode and is also auto-injected in voice mode so the model can send non-spoken text such as long URLs or codes.
- `conversation.escalate_conversation` sets the conversation to `waiting_for_operator` unless it is already escalated or assigned.
- `conversation.escalate_conversation` currently ignores its legacy input payload and acts only on the current conversation run context.
Storage
- Non-system AI teammates are limited to folders explicitly shared with the AI teammate.
- System AI teammates use system-level storage access across the storage tool set.
- `storage.semantic_search` is the meaning-based lookup tool.
- `storage.search` is exact/regex search.
- `storage.stat_file` returns metadata plus bounded `line_count` for supported text files.
- `storage.stat_file` accepts 1 to 10 file paths per call.
- `storage.get_temp_file_url` returns a temporary HTTPS URL for a readable storage file.
- The temporary URL is scoped to the current workflow run and stops working once that run completes or is aborted.
- `storage.get_temp_file_url` is intended for downstream systems that need a URL rather than inline bytes.
- `storage.get_temp_file_url` currently returns `File not found` when the file does not yet have an `OrganizationDocument` record.
- `storage.read_file` reads 1 to 5 files by line range.
- `storage.read_image` returns only the normalized storage path and MIME type. The executor then reinjects the actual bytes into the next model step when needed.
- `storage.write_file` and `storage.edit_file` support text formats only: `.txt`, `.md`, `.htm`, `.html`, `.csv`, `.json`, `.yaml`, and `.yml`.
- `storage.rename`, `storage.copy`, and `storage.move` enforce shared-folder permissions and path-traversal checks for non-system teammates.
Scheduler
- `scheduler.set_reminder` schedules the current employee's default `employee` workflow with `{ message }`.
- `scheduler.schedule_skill_run` takes `skill_id`, `payload`, `at`, and optional `repeat.every_minutes`.
- Scheduler datetime inputs currently accept ISO 8601 timestamps with timezone offsets.
- Recurring intervals are minute-based only, with a minimum of 10 minutes.
- Reminder and skill-run scheduling require a live workflow run context and reject target-organization execution.
- `scheduler.schedule_skill_run` only works for skills assigned to the current employee.
- `scheduler.list_scheduled_items` returns a preview when `item_type` is omitted; full cursor pagination works only within a single `item_type`.
- `scheduler.list_runs` returns execution history for reminder and skill-run jobs, filtered by scheduled job record creation time rather than actual fire time.
- `scheduler.cancel_scheduled_item` and `scheduler.reschedule_item` use normalized refs such as `job:<uuid>` and `schedule:<uuid>`.
- Scheduler tools only operate on items owned by the current employee and reject target-organization execution.
System documentation tools
- `system.list_documentation` lists accessible documentation storage content.
- `system.search_documentation` performs semantic search across documentation chunks.
- `system.read_documentation` reads documentation files by line range.
- These documentation tools are system-only and use the canonical Ally configured through platform settings.
Output shaping
- Tool execution goes through `toolExecutor`.
- If `result.data` serializes above about 40,000 characters, the backend middle-truncates it, replaces `data` with the truncated serialized string, and sends a Telegram alert with the omitted size.