Bluestep JS Documentation
    Preparing search index...

    Class AiToolFactory

    Helpers that auto-generate AiTools from Relate form metadata.

    const tool = B.ai.tool.custom() .setName("resident_allergies") .setDescription("Lists a resident's known allergies") .setSchema({ type: "object", properties: { id: { type: "string" } }, required: ["id"] }) .setExecutor((args) => allergiesFor(args.id).join(", "));

    B.ai.call({ message: B.net.request.parameter("q"), tools: [tool] });

      
    @category
    Index
    • Expose an agent to another agent as a tool. The parent model calls it by name with a message; the sub-agent answers that message with its own model, its own system prompt and its own tools, and its final text is what the parent is shown. Nothing else crosses: the sub-agent's transcript stays on the sub-agent, so the parent pays for one tool result rather than for everything the sub-agent read.

      The sub-agent keeps its conversation between calls, exactly as it would if the script drove it — a second call from the parent continues the first. Give it a fresh B.ai.agent(...) where that is not what you want.

      const researcher = B.ai.agent({ systemPrompt: "You look things up and answer briefly.", tools: [search] });
      const ask = B.ai.tool.agent(researcher, {
      name: "ask_researcher",
      description: "Ask for a fact about a resident's chart. One question at a time.",
      });
      B.ai.call({ message, tools: [ask] });

      Nesting is capped (bluestep.ai.max-nesting, three by default): a sub-agent may have sub-agents of its own, but not without end.

      Only a finished turn is an answer. A turn the usage gate denied, a turn the sub-agent's own hook left deferred, and a turn that stopped at a cap or a hook are each reported to the parent model as a tool failure, and the tool is then withdrawn for the rest of the call — none of them is something the parent could fix by asking again. A deferred turn is also undone on the sub-agent, so it stays usable afterwards.

      Parameters

      • agent: AiAgent

        The sub-agent to expose. Configure it fully before passing it.

      • options: AiToolForAgentOptions

        Tool name and description, both required.

      Returns AiTool

    • 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);

      Returns AiToolBuilder

    • 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] });

      Parameters

      Returns AiTool

    • Auto-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] });

      Parameters

      Returns AiTool

    • Returns 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.

      Parameters

      • tool: AiTool

        The tool whose input_schema should be JS-wrapped.

      Returns object