Appearance
Custom Tools
A custom tool is a reusable JavaScript function that your agents can call during runs and chat sessions.
Connections give your agents access to external services. Custom tools let you extend what agents can do with your own code — data transformations, calculations, formatting, validation, or any logic you want to encapsulate and reuse across workflows.
What It Does
- Extends agent capabilities — write JavaScript functions that agents call like any other tool.
- Reusable across agents and workflows — define once, use everywhere.
- Sandboxed execution — code runs in an isolated environment with no access to your filesystem, network, or system APIs.
- AI-assisted creation — describe what you want in plain language and Pencel generates the tool code and input schema for you.
- Self-healing — tools that fail repeatedly are automatically disabled to prevent cascading errors.
Key Properties
| Property | Description |
|---|---|
| Name | Display name for the tool |
| Description | What the tool does (shown to agents so they know when to use it) |
| Input Schema | JSON Schema defining the parameters the tool accepts |
| Code | JavaScript function body that executes when the tool is called |
| Status | Active or Disabled — disabled tools are not offered to agents |
| Usage Count | How many times the tool has been called |
| Failure Count | Consecutive failures — resets to 0 on success |
| Last Error | Most recent error message, if any |
How It Works
When an agent calls a custom tool, Pencel:
- Validates the input against the tool's JSON Schema.
- Spawns a sandboxed worker thread.
- Runs your JavaScript code with the validated input.
- Returns the result to the agent (or an error message if execution fails).
The tool appears in the agent's tool list as custom_{id}, keeping it distinct from built-in tools and MCP tools.
Sandbox Security
Custom tool code runs in a strict sandbox with these constraints:
| Constraint | Detail |
|---|---|
| Runtime | vm.runInNewContext with an empty prototype chain |
| Timeout | 5 seconds maximum execution time |
| No I/O | No require(), no import, no filesystem access |
| No globals | No process, Buffer, setTimeout, fetch, or other Node.js APIs |
| Input isolation | Arguments are deep-cloned before entering the sandbox |
| Output sanitization | Results are JSON-serialized to strip non-serializable values |
This means custom tools are safe for pure computation — math, string manipulation, data transformation, formatting — but cannot make network requests, read files, or interact with the operating system.
TIP
If you need a tool that accesses external services, use a Connection instead. Custom tools are for logic, not I/O.
Auto-Disable
If a custom tool fails 3 times in a row, Pencel automatically disables it. This prevents a broken tool from wasting tokens and blocking agent progress.
- The failure count resets to 0 after any successful execution.
- You can re-enable a disabled tool from the Custom Tools view — this resets the failure count.
- Check the Last Error field to understand what went wrong before re-enabling.
AI-Assisted Creation
You do not need to write the code yourself. Pencel's tool wizard lets you describe what you want in plain language:
- Open the Custom Tools view.
- Click Create Tool.
- Describe the tool's purpose (e.g., "Calculate the compound annual growth rate given a start value, end value, and number of years").
- Pencel generates the tool name, description, input schema, and JavaScript code.
- Review and edit the generated code if needed.
- Save the tool.
Example Tools
Currency Formatter
- Input:
{ amount: 1234.5, currency: "USD" } - Output:
"$1,234.50"
Slug Generator
- Input:
{ title: "My Blog Post Title" } - Output:
"my-blog-post-title"
CAGR Calculator
- Input:
{ startValue: 100, endValue: 200, years: 5 } - Output:
{ cagr: 0.1487, formatted: "14.87%" }
When to Use Custom Tools vs. Other Options
| Need | Use This |
|---|---|
| Pure computation or formatting | Custom Tool |
| Access an external API | Connection (MCP integration) |
| Run code with full Node.js access | run_code built-in tool (also sandboxed, but one-off) |
| Complex multi-step logic | Workflow with multiple steps |
