Skip to content

Spaces — Built-in Tools

Built-in tools are platform-owned capabilities that ship with ThinkWork itself. They are distinct from MCP servers and workspace skills: MCP servers are remote endpoints ThinkWork connects to at runtime, workspace skills are operator-editable files under workspace/skills/, and built-in tools are registered by the runtime from tenant, Space, and platform-agent policy.

App route: /settings/tools

Docs route: /applications/admin/builtin-tools/

File: apps/web/src/components/settings/SettingsTools.tsx

The catalog is deliberately small. Five built-in tools ship in the current release:

ToolRuntime toolKindProviderCurrent control
Browser Automationbrowser_automationPolicy-gatedagentcore+nova_actPlatform agent and Space runtime/tool policy
Code Sandboxexecute_codePolicy-gatedagentcoreTenant sandbox policy, platform agent, and Space runtime policy
Send Emailsend_emailPolicy-gatedthinkwork-emailSpace email/channel policy and platform agent access
Web Extractionweb_extractCredentialedFirecrawlTenant Firecrawl credential row plus platform agent access
Web Searchweb_searchCredentialedExa or SerpAPITenant search credential row plus platform agent access

Rows have two different treatments in the list:

  • Credentialed rows open a Configure dialog for provider + API key + test. Web Search and Web Extraction are credentialed built-ins.
  • Policy-gated rows open a read-only Info dialog. Their registration is controlled by tenant policy, Space/runtime policy, platform-agent opt-in, and sometimes provisioning state.

The catalog is defined in both the Spaces UI and backend capability/runtime code. Extending the catalog requires code in both places so the UI, REST API, runtime config resolver, and runtime tool registration agree on the slug and configuration shape.

Do not install built-in tools as workspace skills.

Workspace skills are editable SKILL.md files under workspace/skills/<slug>/. Built-in tools are platform-owned runtime registrations. The runtime can present them to the model with skill-like names such as web_search or send_email, but those implementations are injected from API policy and runtime configuration, not copied into the workspace tree.

This boundary matters for repair and backfill work:

  • Do not create workspace/skills/web-search/SKILL.md.
  • Do not create workspace/skills/agent-email-send/SKILL.md.
  • Keep built-in slugs filtered through packages/api/src/lib/builtin-tool-slugs.ts.
  • Use the Spaces Built-in Tools surface and platform-agent configuration to inspect effective access.

See docs/solutions/best-practices/injected-built-in-tools-are-not-workspace-skills-2026-04-28.md for the engineering pattern.

A DataTable showing every built-in tool and its current state:

ColumnNotes
Tool nameDisplay name, such as Web Search or Send Email
ProviderBadge showing a selected provider, such as Exa, or a fixed platform provider such as agentcore
PlatformEnabled / Disabled / Not Configured for credentialed rows; policy/provisioning state for policy-gated rows
Agent accessEffective access for the tenant platform agent, including blocked or missing provider states
API Key”Set” if a credential is stored, ”—” otherwise

Clicking a credentialed row opens the Configure dialog. Clicking a policy-gated row opens a read-only info dialog that explains the platform, tenant, Space, or platform-agent policy that controls the tool.

Credentialed built-ins use the same Configure dialog. It captures:

  • Provider — dropdown populated from the tool’s available providers list
  • API Key — password input; placeholder hides the stored key if one already exists
  • Enabled — toggle
  • Test — button that fires the test endpoint and surfaces the result inline
  • Delete — only visible once the tool has been configured

Saving goes through PUT /api/skills/builtin-tools/:slug with { provider, enabled, apiKey? }. The backend writes the API key to Secrets Manager and stores a secret reference on the tenant_builtin_tools row. The UI gets back a hasSecret boolean it uses to decide whether to show the placeholder or the “Set API key” state on subsequent visits.

  • Web Search (web_search) finds candidate URLs and search results through Exa or SerpAPI. It is the discovery tool.
  • Web Extraction (web_extract) reads one known public HTTPS URL through Firecrawl and returns clean markdown/text plus source metadata. It is the page-reading tool.
  • Browser Automation (browser_automation) remains the interactive fallback for pages that require clicks, forms, rendered-state inspection, login flows, or cases where extraction fails.

The intended research sequence is: search for promising URLs with Web Search, read selected pages with Web Extraction, and only open Browser Automation when the task actually needs browser interaction.

EndpointPurpose
GET /api/skills/builtin-toolsList credentialed built-in tool configuration rows
PUT /api/skills/builtin-tools/:slugUpsert provider, key, or enabled state for a credentialed built-in
DELETE /api/skills/builtin-tools/:slugRemove a credentialed built-in configuration
POST /api/skills/builtin-tools/:slug/testTest the current or provided credentialed configuration

All requests carry tenant context in the request headers.

The Test button fires a provider-specific call and returns { ok: boolean; resultCount?: number; error?: string }.

  • Web Search runs a canonical query against Exa or SerpAPI.
  • Web Extraction asks Firecrawl to scrape https://example.com/ as markdown.

If the test succeeds, a toast shows the result count. If it fails, the error message surfaces inline so the operator can diagnose.

Testing does not require saving first — the dialog lets the operator test with a new key before committing it to the vault.

Browser Automation, Code Sandbox, and Send Email are policy-gated rows. Unlike Web Search, there is no provider API key to configure on this page. Clicking one of these rows opens a read-only Info dialog, not the Configure dialog.

The dialog shows:

  • Provider - a fixed provider badge, such as agentcore, agentcore+nova_act, or thinkwork-email.
  • Status - for Code Sandbox, tenant provisioning state. Other tools show whether the tenant-side prerequisite is available.
  • Space or platform-agent opt-in - Space-aware flows should be controlled by the current Space surfaces and runtime policy; older template-backed flows remain legacy where they still exist.
  • Tenant or Space policy - extra gates such as sandbox_enabled, Space-local policy, or Space tool availability.

Registration rules:

  • execute_code registers only when tenant policy allows the sandbox and the current Space runtime/tool policy allows it.
  • browser_automation registers when tenant policy and the current Space/tool policy allow it.
  • send_email registers when Space email/channel policy can provide the sending address and delivery policy.
  • web_search registers when the tenant has a configured/enabled provider row and the current Space/tool policy allows it.
  • web_extract registers when the tenant has a configured/enabled Firecrawl row and the current Space/tool policy allows it.

See the Code Sandbox concept page for the sandbox-specific runtime flow.

Built-in tools do not get assigned like skills or MCP servers. They are injected into a turn by the runtime config resolver:

  • Tenant-level provider or policy enables the tool family.
  • Space tool and runtime policy determine whether the current Space can use it.
  • Legacy Agent Template configuration can still participate where that UI owns an existing flow, but Spaces is the active operator surface.
  • Tenant disabled built-ins narrow the final toolset.
  • tenant_builtin_tools - one row per (tenant_id, tool_slug) for credentialed provider tools such as Web Search and Web Extraction.
  • agent_templates.web_search - template opt-in metadata for the tenant-configured web_search built-in.
  • agent_templates.web_extract - template opt-in metadata for the tenant-configured web_extract built-in.
  • agent_templates.send_email - template opt-in metadata for the injected send_email built-in.
  • agent_templates.browser - template opt-in metadata for Browser Automation.
  • agent_templates.sandbox - template opt-in metadata for Code Sandbox, including network mode.
  • Secrets Manager - API keys are stored under references like thinkwork/{stage}/builtin-tools/{tenant_id}/{tool_slug}.

The Spaces UI never receives a plaintext API key after the initial save. Subsequent loads see hasSecret: true and render a placeholder in the password input.

  1. Open /settings/tools in Spaces
  2. Click the Web Search row → Configure dialog opens
  3. Pick a provider (Exa is recommended for cost and result quality)
  4. Paste the API key
  5. Click Test — verify the result count comes back non-zero
  6. Set Enabled = true
  7. Save
  8. Confirm the platform agent access badge is enabled or resolve the policy shown in the row/dialog.
  9. New eligible turns can receive web_search.

Configure Web Extraction for the first time

Section titled “Configure Web Extraction for the first time”
  1. Open /settings/tools in Spaces
  2. Click the Web Extraction row → Configure dialog opens
  3. Select Firecrawl
  4. Paste the Firecrawl API key
  5. Click Test — verify the scrape result count comes back non-zero
  6. Set Enabled = true
  7. Save
  8. Confirm the platform agent access badge is enabled or resolve the policy shown in the row/dialog.
  9. New eligible turns can receive web_extract
  1. Open the Configure dialog for Web Search
  2. Change the provider dropdown
  3. Paste the new provider’s API key
  4. Test
  5. Save

Switching providers does not flush in-flight agent invocations, but the next invocation will use the new provider.

  1. Open Configure
  2. Toggle Enabled to false
  3. Save

All Spaces stop receiving web_search, even when their local tool policy allows it. Re-enabling the tenant row restores it for Spaces that allow the tool.

  1. Open the relevant Space
  2. Go to the Triggers tab
  3. Use Add -> Email to enable the Space email trigger
  4. Click the Email row to copy, rename, disable, or delete the Space email address
  5. Confirm send/reply behavior with an approved test message

The runtime injects send_email as a direct platform tool. It does not install agent-email-send as a workspace skill.

  • CLI only manages Web Search today. Spaces shows Web Extraction and policy-gated tools, but thinkwork tools currently configures only credentialed Web Search.
  • No per-agent API key or per-agent provider override. Web Search and Web Extraction provider configuration is tenant-level.
  • Hardcoded catalog in multiple places. Adding a new built-in tool requires code changes in the Spaces UI, API/runtime config resolver, and managed runtime registration.
  • No key format validation. The Test button catches bad keys; there is no pre-submit format check.
  • Send Email smoke requires care. A true end-to-end send test emits a real email. Prefer runtime-config checks and explicit user-approved send tests.
  • Tenant MCP Servers — the other path for exposing external capabilities
  • Skills Catalog — the third path: reusable skill packs with embedded tools
  • Spaces — current Space Studio tabs and local policy context
  • Agent Templates — legacy/template-backed built-in tool opt-ins