Skip to main content
Custom tools are a beta surface. Validate them in the sandbox before assigning them to production agents.
A custom tool is a TypeScript module that default-exports defineTool. Its name must match ^[a-z][a-z0-9_]*$ and an agent must list that exact name in allowedTools. For the example below, configure an API Connector named billing with the service origin, credential attachment, and permission to POST /invoices. Create its Connection and grant create_invoice to the selected agent.
create_invoice.ts
execute returns a string or a ToolResult.

Execution context

Custom tools receive only their declared, authorized Connection capabilities; there is no ambient project account inventory. Slots are separate from model-facing parameters. Two execution modes coexist:
  • gateway: call ctx.connections.require(slot).request(...) with a provider-relative path. The host selects the account, checks current grants, and attaches credentials outside the sandbox. getToken, getKey, and getHeaders are unavailable on a gateway slot.
  • legacy_credentials: use getToken, getKey, or getHeaders when Git, HMAC, an SDK or another native operation needs a credential. An omitted mode retains this compatibility meaning. Cloud also requires explicit operator consent for the exact credential slot; the tool declaration cannot authorize itself.
For example, a repository_checkout tool can declare a github slot with mode: "legacy_credentials". An administrator separately grants it access:
Clearing credential consent does not rewrite the tool to use the gateway. A subsequent direct credential request is denied until consent is granted again. There is no fallback from a denied gateway request to credential export. Direct tool code must keep credentials out of results, logs and model arguments. The exported credential retains its provider permissions; Polpo slot scopes and HTTP gateway policy cannot constrain requests made with an already copied token. Revocation prevents future credential delivery but cannot recall a copied token. A key-only record remains useful for this explicitly authorized direct mode; define its API destination and request policy before using it through a gateway. Agent-level Vault compatibility is a separate surface and remains available.
site_update.ts
Strict slots fail closed when no Connection matches, more than one matches, the grant is missing, or required scopes are unavailable. They never fall back to an arbitrary project Connection. A capability is valid only during the current tool invocation.

Trusted invocation bindings

Use trusted bindings when a tool must receive application identity or authorization data that the model must not supply. Binding fields are separate from parameters, are not included in the model-facing tool schema, and are resolved immediately before execution.
site_context_get.ts
Supported binding roots are invocation.requestId, invocation.runId, invocation.sessionId, invocation.user, invocation.surface, and nested invocation.metadata.* JSON values. A missing or schema-invalid required value fails the tool before execute runs. Model arguments cannot override a binding with the same name. For durable loop resumes, trusted values are not restored from a persisted private snapshot. The host must re-authorize them through the invocation resolver; a missing or changed identity fails closed.

Dependencies and bundling

Cloud detects imported npm packages, installs them with lifecycle scripts disabled, and bundles the tool with esbuild for Node 22. Pure JavaScript dependencies are supported. Native addons containing .node binaries or binding.gyp are rejected; choose a pure JavaScript alternative. From 0.15.66, a tool entrypoint may import relative TypeScript, JavaScript, TSX, or JSON modules in the same source directory. The CLI resolves the static local graph and uploads one versioned artifact. Cycles and literal dynamic imports are supported. Computed dynamic imports, symlinks, files outside the tool directory, path traversal, and unsupported paths fail before upload. @polpo-ai/tools and @sinclair/typebox are runtime externals and do not need to be bundled.

Manage tools

polpo deploy also synchronizes .polpo/tools/*.ts. The Agent API exposes the same registry:
Saving source and deploying a bundle are distinct API operations. The CLI and dashboard perform both steps for you.

Application databases

Use ctx.data for structured records or scoped SQL on Databases. The host supplies it only when Data is configured and enabled. Check availability; query is optional for providers without SQL. Never accept provider credentials, project identity or extra grants from model arguments.
execute runs atomic structured batches. query supports one scoped SQL statement; mutations require mode: "write" and a write grant. Use an idempotency key when retrying writes. Database creation and migrations are administrative API/SDK/CLI operations.