Open a builder for a fully-typed custom AI tool. Chain
.setName(...), .setDescription(...), .setSchema(...), then
.setExecutor(...) on the typed builder returned by setSchema;
setSchema captures the schema literal's type so setExecutor's
args parameter is typed via FromSchema<S> — eliminating drift
between the input_schema sent to the model and the JS function that
reads its arguments. The terminal setExecutor(...) call returns the
built AiTool.
const tool = B.ai.tool.custom()
.setName("add_1")
.setDescription("adds one!")
.setSchema({
type: "object",
properties: {
a: { type: "integer" },
b: { type: "integer" },
},
required: ["a", "b"],
})
.setExecutor((args) => args.a + args.b + 1);
Auto-generate an AiTool that updates an existing entry. The same entry
is mutated on every tool invocation within a single B.ai.call — useful
for incrementally refining a record from narration. Pass afterApply
for derived state the model can't produce.
The default required list is empty: for an update the model is
expected to supply only the fields it intends to change. Use
options.required if you want to force certain fields.
const mar = thisRecord.forms.marMedsToBeAdministeredToday.optById(marId).orElseThrow();
const tool = B.ai.tool.forExistingEntry(mar, {
description: "Sign off the MAR entry the caregiver just administered.",
include: [],
afterApply: (entry) => entry.fields.adminSig.sign(Date.now()),
});
B.ai.call({ message, tools: [tool] });
The form entry to update.
Optionaloptions: AiToolForExistingEntryOptionsAuto-generate an AiTool that creates a new entry on a multi-entry form.
The executor calls form.newEntry() per invocation and applies the
model's args to the fresh entry. Pass afterApply for derived state
the model can't produce (e.g. signing a signature with the current
time).
The default required list is every included field that is marked
required in the form definition (field.metaData().required()).
Override with options.required (pass [] to relax everything).
const tool = B.ai.tool.forNewEntry(thisRecord.forms.nursingNotes, {
description: "Capture a nursing note from the caregiver's narration.",
exclude: ["staffSig"],
afterApply: (entry) => entry.fields.staffSig.sign(Date.now()),
});
B.ai.call({ message, systemPrompt, tools: [tool] });
The multi-entry form to create entries on.
Optionaloptions: AiToolForNewEntryOptionsReturns a JS-friendly view of an AiTool's input_schema — safe to
pass to JSON.stringify and member-accessible at every nesting level.
Returns null when the tool has no input_schema set.
The wrap is necessary because tools built via the Relate-form
auto-generators store their schema as a Java Map/List tree, which
JS would otherwise see as host-class members (.put, .get, etc.)
instead of as ordinary object/array entries. Tools authored from a JS
literal already store a Polyglot value and pass through unchanged.
The tool whose input_schema should be JS-wrapped.
Helpers that auto-generate AiTools from Relate form metadata.