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
What’s in the catalog
Section titled “What’s in the catalog”The catalog is deliberately small. Five built-in tools ship in the current release:
| Tool | Runtime tool | Kind | Provider | Current control |
|---|---|---|---|---|
| Browser Automation | browser_automation | Policy-gated | agentcore+nova_act | Platform agent and Space runtime/tool policy |
| Code Sandbox | execute_code | Policy-gated | agentcore | Tenant sandbox policy, platform agent, and Space runtime policy |
| Send Email | send_email | Policy-gated | thinkwork-email | Space email/channel policy and platform agent access |
| Web Extraction | web_extract | Credentialed | Firecrawl | Tenant Firecrawl credential row plus platform agent access |
| Web Search | web_search | Credentialed | Exa or SerpAPI | Tenant 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.
Built-ins vs workspace skills
Section titled “Built-ins vs workspace skills”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.
The list view
Section titled “The list view”A DataTable showing every built-in tool and its current state:
| Column | Notes |
|---|---|
| Tool name | Display name, such as Web Search or Send Email |
| Provider | Badge showing a selected provider, such as Exa, or a fixed platform provider such as agentcore |
| Platform | Enabled / Disabled / Not Configured for credentialed rows; policy/provisioning state for policy-gated rows |
| Agent access | Effective 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.
Configuring credentialed tools
Section titled “Configuring credentialed tools”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 vs Web Extraction
Section titled “Web Search vs Web Extraction”- 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.
REST endpoints
Section titled “REST endpoints”| Endpoint | Purpose |
|---|---|
GET /api/skills/builtin-tools | List credentialed built-in tool configuration rows |
PUT /api/skills/builtin-tools/:slug | Upsert provider, key, or enabled state for a credentialed built-in |
DELETE /api/skills/builtin-tools/:slug | Remove a credentialed built-in configuration |
POST /api/skills/builtin-tools/:slug/test | Test the current or provided credentialed configuration |
All requests carry tenant context in the request headers.
Testing
Section titled “Testing”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.
Policy-gated tools
Section titled “Policy-gated tools”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, orthinkwork-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_coderegisters only when tenant policy allows the sandbox and the current Space runtime/tool policy allows it.browser_automationregisters when tenant policy and the current Space/tool policy allow it.send_emailregisters when Space email/channel policy can provide the sending address and delivery policy.web_searchregisters when the tenant has a configured/enabled provider row and the current Space/tool policy allows it.web_extractregisters 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.
Availability in Spaces
Section titled “Availability in Spaces”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.
Data model
Section titled “Data model”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-configuredweb_searchbuilt-in.agent_templates.web_extract- template opt-in metadata for the tenant-configuredweb_extractbuilt-in.agent_templates.send_email- template opt-in metadata for the injectedsend_emailbuilt-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.
Workflows
Section titled “Workflows”Configure Web Search for the first time
Section titled “Configure Web Search for the first time”- Open
/settings/toolsin Spaces - Click the Web Search row → Configure dialog opens
- Pick a provider (Exa is recommended for cost and result quality)
- Paste the API key
- Click Test — verify the result count comes back non-zero
- Set Enabled = true
- Save
- Confirm the platform agent access badge is enabled or resolve the policy shown in the row/dialog.
- New eligible turns can receive
web_search.
Configure Web Extraction for the first time
Section titled “Configure Web Extraction for the first time”- Open
/settings/toolsin Spaces - Click the Web Extraction row → Configure dialog opens
- Select Firecrawl
- Paste the Firecrawl API key
- Click Test — verify the scrape result count comes back non-zero
- Set Enabled = true
- Save
- Confirm the platform agent access badge is enabled or resolve the policy shown in the row/dialog.
- New eligible turns can receive
web_extract
Switch providers
Section titled “Switch providers”- Open the Configure dialog for Web Search
- Change the provider dropdown
- Paste the new provider’s API key
- Test
- Save
Switching providers does not flush in-flight agent invocations, but the next invocation will use the new provider.
Disable temporarily
Section titled “Disable temporarily”- Open Configure
- Toggle Enabled to false
- 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.
Enable Space email
Section titled “Enable Space email”- Open the relevant Space
- Go to the Triggers tab
- Use Add -> Email to enable the Space email trigger
- Click the Email row to copy, rename, disable, or delete the Space email address
- 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.
Known limits
Section titled “Known limits”- CLI only manages Web Search today. Spaces shows Web Extraction and policy-gated tools, but
thinkwork toolscurrently 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.
Related pages
Section titled “Related pages”- 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