Skip to main content

Tool Invocation Helper

The tools helper lets a script invoke any published tool in its company by id — the same tools your agents call, executed through the same config, permission, and variable-substitution pipeline. It turns a script into an orchestrator: fetch with one tool, decide in code, write with another.

tools.invokeById​

  • Name
    tools.invokeById
    Type
    (toolId: string, variablesJson?: string) => string
    Description

    Invokes the tool with the given id and returns its result as a JSON string. toolId is the tool's ID string ("V1StGXR8Z5"). variablesJson is an optional JSON object string supplying values for the tool's declared @@{name} placeholders; pass null or omit it for none.

There is deliberately no invoke-by-type: scripts reference concrete, published tools that users can see, edit, and revoke in the tool builder — never anonymous tool types. See Tools for how tools are published.

How variables merge into the tool​

The invoked tool's stored config is the source of truth — you never override its shape, you only fill in the @@{name} placeholders it declares:

  • Strings, numbers, booleans become string substitutions for matching @@{name} placeholders anywhere in the config. null substitutes an empty string.
  • Objects and arrays can't survive string substitution into typed config fields, so they are spliced in raw — but only where a config field's value is exactly "@@{name}". A placeholder embedded inside a longer string only accepts scalar values.
  • The enclosing script's own variables (including platform context like AUTESSA_COMPANY_ID and private variables) are inherited by the invoked tool automatically — you don't forward them yourself.
// Tool V1StGXR8Z5 is an AutessaDB update tool whose config contains
// "values": "@@{values}" and "rowId": "@@{rowId}"
const result = tools.invokeById("V1StGXR8Z5", JSON.stringify({
rowId: 99, // scalar -> string substitution
values: { summary: { textValue: "hello" } } // object -> spliced raw
}));

Access rules​

  • Same company only. The tool must belong to the company the script runs in; anything else returns CROSS_COMPANY.
  • Permissions apply. Tools private to another user, without an explicit grant, are refused — the invocation goes through the same permission pipeline as agent and API calls.

Return envelope​

On success you get the invoked tool's result as a JSON string, unwrapped so a single JSON.parse works regardless of how the executor produced it:

  • A structured result (object/array) arrives as that JSON document.
  • A result that was already a JSON string arrives verbatim — no double-encoding, one JSON.parse is enough.
  • A plain-text or numeric result arrives as a valid JSON literal (e.g. "done" or 123), so JSON.parse never fails.

On failure you get an error envelope instead:

{ "error": true, "errorCode": "TOOL_NOT_FOUND", "errorMessage": "No tool with id V1StGXR8Z5" }

Always check for error before using the result:

const parsed = JSON.parse(tools.invokeById("V1StGXR8Z5"));
if (parsed && parsed.error) {
console.error("tool failed:", parsed.errorCode, parsed.errorMessage);
}

Error codes​

  • Name
    BAD_TOOL_ID
    Type
    errorCode
    Description

    toolId couldn't be resolved — null, empty, not a valid tool ID, or an unsupported type.

  • Name
    NO_SPRING_CONTEXT
    Type
    errorCode
    Description

    The platform application context wasn't available yet; retry later.

  • Name
    TOOL_NOT_FOUND
    Type
    errorCode
    Description

    No tool exists with that id.

  • Name
    MISSING_COMPANY_ID
    Type
    errorCode
    Description

    The script has no company id in context (e.g. a computed column) — company-scoped dispatch is refused.

  • Name
    BAD_COMPANY_ID
    Type
    errorCode
    Description

    The company id in context wasn't a valid number.

  • Name
    CROSS_COMPANY
    Type
    errorCode
    Description

    The tool belongs to a different company.

  • Name
    BAD_TOOL_CONFIG
    Type
    errorCode
    Description

    The tool exists but its stored config is unreadable or has no tool type.

  • Name
    INVALID_CONFIG
    Type
    errorCode
    Description

    Building the executable config failed — usually a missing or wrongly-typed variable for a required placeholder.

  • Name
    NULL_RESULT
    Type
    errorCode
    Description

    The executor ran but produced no result.

  • Name
    EXECUTION_ERROR
    Type
    errorCode
    Description

    The tool executed and failed; errorMessage carries the underlying cause.

Composition pattern: script as orchestrator​

The canonical use is read → decide → write, with each side effect going through a published, user-visible tool:

// 1. Read: a query tool returns matching rows.
const rows = JSON.parse(tools.invokeById("kA9mB2xQ7p", JSON.stringify({
status: "overdue"
})));
if (rows.error) {
response.setResponse(JSON.stringify({ error: rows.errorMessage }));
} else {
// 2. Decide: pure JavaScript in between.
const toEscalate = rows.filter(r => parseInt(r.daysOverdue) > 30);
console.log("escalating", toEscalate.length, "of", rows.length, "rows");

// 3. Write: an update tool per row.
const failures = [];
for (const row of toEscalate) {
const res = JSON.parse(tools.invokeById("pQ4rT8nW2c", JSON.stringify({
rowId: row.id,
values: { priority: { textValue: "high" } }
})));
if (res && res.error) failures.push({ rowId: row.id, error: res.errorCode });
}

response.setResponse(JSON.stringify({
escalated: toEscalate.length - failures.length,
failures: failures
}));
}

Each invokeById call is synchronous and runs the full tool pipeline. Loops over many rows work, but budget accordingly — prefer a tool that operates on batches when one exists.