Built-in Tools
Provider-specific server-side tools like web search, and how to integrate them.
Built-in tools are capabilities provided natively by the AI provider and executed server-side. Unlike MCP tools or Cosmo's internal tools (tasks, workspaces, artifacts), built-in tools don't go through the engine's tool executor — the provider handles everything.
Architecture
The built-in tools system is designed to be provider-agnostic. Each provider declares what built-in tools it supports, and the engine automatically enables the ones configured in LLMConfig.
Type Definitions
interface BuiltInToolConfig {
/** Tool identifier — e.g., 'web_search'. */
type: string
/** Max number of uses per request (provider-specific). */
maxUses?: number
}
interface LLMConfig {
provider: 'anthropic' | 'openai'
model: string
apiKey?: string
/** Enable provider-specific built-in tools. */
builtInTools?: BuiltInToolConfig[]
}Provider Interface
Providers declare their capabilities via supportedBuiltInTools:
interface LLMProvider {
readonly name: string
readonly supportedBuiltInTools?: string[]
chat(messages, tools, opts): AsyncIterable<ChatChunk>
}How It Works
- Configuration — The engine is created with
builtInToolsin the LLM config - Provider mapping — Each provider maps generic
BuiltInToolConfigto its native format (e.g., Anthropic'sWebSearchTool20250305) - Streaming — Server-handled tool calls come back as
tool_callchunks withserverHandled: true - Engine loop — The agentic loop skips execution for server-handled calls; they resolve within a single provider turn
- UI — Server-handled tools look identical to regular tools in the event stream (spinner → checkmark)
Available Built-in Tools
Web Search
| Property | Value |
|---|---|
| Type | web_search |
| Supported by | Anthropic |
| Enabled by default | Yes (in desktop) |
Allows the AI to search the web for current information. The provider executes the search server-side and returns results inline.
Configuration:
const engine = createEngine({
mode: 'local',
llm: {
provider: 'anthropic',
model: 'claude-haiku-4-5-20251001',
apiKey: '...',
builtInTools: [
{ type: 'web_search', maxUses: 5 },
],
},
})Stream behavior:
The Anthropic provider handles two special content block types:
server_tool_use— Emitted when the model decides to search. The provider yields atool_callchunk withserverHandled: true.web_search_tool_result— Emitted when search results arrive. The provider yields atool_resultchunk.
These events happen within a single provider turn. The engine does not re-enter the agentic loop for them.
ToolCall.serverHandled Flag
interface ToolCall {
id: string
name: string
args: Record<string, unknown>
serverId?: string
/** True when the provider executed this tool server-side. */
serverHandled?: boolean
}The engine uses this flag to decide whether to execute a tool call:
// In the agentic loop
if (chunk.toolCall.serverHandled) {
serverHandledCalls.push(chunk.toolCall) // Track for history, don't execute
} else {
pendingToolCalls.push(chunk.toolCall) // Execute via tool registry
}Adding a New Built-in Tool
To add support for a new provider-specific tool:
- Add the type to
BuiltInToolConfigmapping in the relevant provider (e.g.,toAnthropicBuiltInTool()inanthropic.ts) - Handle stream events for the new tool type in the provider's streaming loop
- Update
supportedBuiltInToolson the provider class - Yield
tool_callwithserverHandled: trueso the engine skips execution - Yield
tool_resultwhen the server-side execution completes
No changes needed in the engine, router, or other providers — the abstraction handles it.
Provider Compatibility
If a built-in tool is configured but the active provider doesn't support it, the tool is silently ignored. This means you can configure builtInTools: [{ type: 'web_search' }] and it will work with Anthropic but have no effect with OpenAI — no errors, no behavior change.