Tools
A tool is a function the model can call. The important distinction is where its implementation runs, because that determines what it can reach and who holds its credentials.
| Kind | Runs on | Reaches | Configured with |
|---|---|---|---|
| Hosted | Coresource | Hosted services and public MCP endpoints | mcpServers, imageModel, derived or explicit allowlist |
| Custom handler | Your process | Whatever your process can reach | tools |
| Runtime catalog | Your process | Your filesystem, shell, network | registerRuntimeTools() |
| Local MCP | Your process | MCP servers reachable from your process | registerMcpServer() |
Hosted tools such as web_search, understand_image, and hosted MCP connections need no callback into your application. Custom handlers, the runtime catalog, and locally registered MCP clients execute through your SDK process.
SDK-hosted tools#
Pass functions in tools and the model calls them by name. When the model calls one, Coresource sends the call over the connection your SDK process holds (the bridge), runs your handler locally, and returns its result to the run.
import { createAgent } from '@coresourceai/sdk';
const agent = createAgent({
type: 'agent',
systemPrompt: 'Use the available business data. Never guess an amount.',
tools: [
{
name: 'lookup_invoice',
description: 'Look up an invoice by ID. Returns vendor, amount, and status.',
inputSchema: {
type: 'object',
properties: { id: { type: 'string' } },
required: ['id'],
additionalProperties: false
},
handler: async (input, { signal }) => {
signal.throwIfAborted();
return lookupInvoice(String(input.id), { signal });
}
}
]
});
const result = await agent.run('Summarise invoice INV-123.');
await agent.close();
declare function lookupInvoice(id: string, options: { signal: AbortSignal }): Promise<unknown>;Connect your own tools covers schema design, cancellation, deadlines, and error handling properly. This page is about how tools are resolved.
Name collisions#
Tool names must match ^[A-Za-z][A-Za-z0-9_-]{0,63}$. A letter, then up to 63 letters, digits, underscores, or hyphens. A name that does not is rejected with a TypeError when the agent is created, because provider APIs will not accept it.
Two of your own tools sharing a name is also a TypeError; that is a mistake, not a configuration choice.
A tool of yours sharing a name with a runtime-catalog tool is not an error. Yours wins. That is the supported way to substitute your own implementation:
import { createAgent } from '@coresourceai/sdk';
const agent = createAgent({
type: 'agent',
tools: [
{
name: 'execute',
description: 'Run a command inside the job sandbox.',
inputSchema: {
type: 'object',
properties: { command: { type: 'string' } },
required: ['command'],
additionalProperties: false
},
handler: (input) => runInSandbox(String(input.command))
}
]
});
// Replaces the catalog's `execute`; every other catalog tool is untouched.
agent.registerRuntimeTools();
await agent.close();
declare function runInSandbox(command: string): Promise<string>;The allowlist#
toolAllowlist is the list of tool names the model may see. Leave it unset and the SDK derives one from your configuration:
| Configuration | Adds |
|---|---|
Custom tools | Each custom tool name |
| Runtime tools registered | Each runtime-catalog tool name plus web_search |
skills present | list_skills, invoke_skill |
mcpServers present | <alias>/*, list_mcp_capabilities, list_mcp_resources, read_mcp_resource |
imageModel set | understand_image |
| Local MCP registered | <namespace>/*, where namespace defaults to the server name |
Set it explicitly to narrow things further:
import { createAgent } from '@coresourceai/sdk';
const agent = createAgent({
type: 'agent',
imageModel: 'makora/kimi-2.7-code',
// Read-only: the agent may look at files and images, but not write or execute.
toolAllowlist: ['file_read', 'glob', 'grep', 'understand_image'],
maxTools: 8
});
agent.registerRuntimeTools();
await agent.close();If an agent stubbornly refuses to use a tool you configured, check the allowlist first. An explicit list that omits the tool is the usual cause.
maxTools caps how many tools the runtime may expose. It is separate from toolAllowlist: the allowlist selects eligible names, while maxTools limits the resulting catalog.
