> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eigenpal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Callback capabilities and limits

> Learn which JavaScript APIs agent tools and evaluation callbacks can use, how compilation detects mistakes, and when you need filesystem sandbox scripts.

Write agent callbacks as small synchronous calculations over explicit inputs.
Custom tools, evaluators, exact-diff selectors, judge selectors and pass rules use
the same isolated QuickJS environment for normal and filesystem agents.

## Supported code

Use strings, finite numbers, booleans, arrays, plain objects, regular expressions,
loops, JSON operations and ordinary `Math` calculations. Import local TypeScript
helpers and captured constants from the source project:

```ts math.ts theme={null}
export const taxRate = 0.2;
export const totalWithTax = (subtotal: number) => subtotal * (1 + taxRate);
```

```ts tools.ts theme={null}
import { createTool } from '@eigenpal/automations';
import { z } from 'zod';
import { totalWithTax } from './math.ts';

export const calculateTotal = createTool({
  description: 'Calculate the total including tax.',
  inputSchema: z.object({ subtotal: z.number().nonnegative() }),
  outputSchema: z.strictObject({ total: z.number() }),
  execute: ({ subtotal }) => ({ total: totalWithTax(subtotal) }),
});
```

The compiler bundles these files. It allows imports of `@eigenpal/automations`,
Zod and captured relative source modules. Zod defines schema contracts; unsupported
parsing effects still [fail schema compilation](/sdks/automations/agents#schema-types-and-validation).

Return JSON-compatible data. Convert internal collections to arrays/plain objects
before returning. Functions, symbols, `bigint`, cycles and non-finite numbers are
unsupported at the boundary. Tools return objects matching `outputSchema`;
evaluators return scores, selectors return JSON data, and pass rules return booleans.

## Unavailable APIs

Callbacks do not receive:

* Node built-ins such as `node:fs`, `child_process`, `Buffer` or `process.env`.
* Network APIs such as `fetch`, database clients or host credentials.
* Arbitrary npm runtime imports, dynamic `import()` or `require()`.
* Browser globals such as `window` or `document`, or host timers such as `setTimeout`.
* A platform client/context for calling another agent, reading a resource file
  directly, invoking built-in resource tools as JavaScript functions or spawning a process.

Async functions, generators and returned Promises are unsupported. Do not write
an asynchronous tool even when its return type matches the desired data:

```ts theme={null}
// Unsupported: no async or network access in execute.
// execute: async ({ url }) => fetch(url).then(response => response.json())

// Unsupported: installing an npm package in a filesystem sandbox does not
// make it an allowed callback import.
// import Decimal from 'decimal.js';
```

## Filesystem scripts versus TypeScript callbacks

`.withFilesystem()` gives the agent sandbox-native read/write/shell tools. Through
those tools, it can execute scripts that use installed Python/npm packages and
workspace files. Those scripts run inside the filesystem sandbox.

It does not move `createTool.execute` or evaluation callbacks into that sandbox
or grant them extra imports. There is no second `execute` mode for Python or shell
scripts. For a file-heavy task, give the filesystem agent instructions and a
[skill directory](/sdks/automations/resources#skills) with its helper scripts.
For structured calculations, use a custom TypeScript tool.

The [resource tools](/sdks/automations/resources#built-in-resource-tools) also work
for normal agents. EigenPal implements them as bounded platform operations. Your
custom callback cannot invoke them through an injected context.

## Invocation and state

EigenPal evaluates declarations in an isolated compiler, then retains the callback
bundle for execution. It does not proactively invoke callback bodies with sample
arguments during compilation. If your own module calls a helper at top level,
that code executes while loading the declaration; keep module initialization portable.

Each callback invocation gets a fresh QuickJS context. A captured helper can use
local constants, but module variables are not persistent storage between calls.
Use explicit inputs; do not mutate evaluation inputs or rely on object identity
with values outside the context.

The runtime reuses the same QuickJS engine as workflow script steps, with
agent-specific input/output contracts and limits. It does not expose arbitrary
workflow-step configuration through the agent SDK.

Declaration compilation disables wall-clock time and random sources. Runtime
callbacks are not guaranteed deterministic. Avoid `Date` and `Math.random` when
you need reproducible decisions; pass timestamps or other values as explicit input.

## Execution limits

Custom tools and evaluation callbacks currently have at most:

* 2 seconds per invocation and 64 MiB of QuickJS memory.
* A 512 KiB stack.
* 128 KiB for tool results and evaluation outputs.
* 256 KiB for evaluation arguments.

Deployment script limits can be tighter. An agent's remaining time can shorten
tool execution further. These are platform limits, not per-callback SDK options.
A deployment can disable script execution; custom callbacks then fail rather than
running on the application host.

## Catch mistakes before release

The [example project](https://github.com/eigenpal/automations/tree/main/examples/agents)
uses a strict authoring configuration that omits Node/browser globals:

```json tsconfig.json theme={null}
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noEmit": true,
    "allowImportingTsExtensions": true,
    "skipLibCheck": true,
    "lib": ["ES2022"],
    "types": []
  },
  "include": ["agents/**/*.ts", "resources/**/*.ts"]
}
```

Run `tsc --noEmit`. Callback parameters, selected output fields and registered
score names infer from your schemas and chain. `lib` and `types` help the IDE flag
`process`, `fetch` and `window`; they do not prevent explicit imports from adding
other ambient types. Keep Bun/Node verification scripts in a separate TypeScript
project, as the example does.

Run `eigenpal agents validate` from the agent package for platform compilation.
Unsupported imports identify their project-relative source file and category.
Async/generator declarations receive synchronous-callback guidance.

Static checks cannot prove arbitrary JavaScript pure, terminating or correct for
all inputs. A synchronous untyped helper could return a Promise or access a global
indirectly. Runtime checks reject returned Promises, invalid scores, schema failures
and exceeded limits. Arbitrary exception text remains private; you receive a
sanitized failure. Test tools and evaluations on representative inputs before release.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.