Class AbstractModelDependentTool<I,O>

java.lang.Object
ai.redouble.nucleo.harness.AbstractJob<O>
ai.redouble.nucleo.tools.AbstractTool<I,O>
ai.redouble.nucleo.tools.AbstractModelDependentTool<I,O>
All Implemented Interfaces:
GuardedExecution, Identifiable, Job<O>, ModelDependent, ModelDependentTool<I,O>, Tool<I,O>
Direct Known Subclasses:
AnalyzeViolationTool, CanonicalizeProductsTool, ClassifyFileTool, ExtractPricesTool, JudgeTool, PdfVisionExtractTool, QuickLLMQuestionTool, SummarizationTool, VisionExtractTool

public abstract class AbstractModelDependentTool<I,O> extends AbstractTool<I,O> implements ModelDependentTool<I,O>
A tool whose work is one exchange with a model. It declares a grade, or is pinned to an entry, and it wires one conversation: the input rendered as the prompt, the response contract from the output POJO, the seat's depth and answer size declared on it. The shape: in getRequirements, wireConversation(JobRequirements, Depth, OutputDeclaration, Class, String); in execute, converse(JobResources), wrapped in catch (Exception e) { throw LLMReadableCheckedException.unwrap(e); }. QuickLLMQuestionTool is the reference.

The grade arrives in the constructor, or later through setGrade(Grade) for a tool whose grade is its input's or its parent's; the wiring reads it at requirements time. The conversation is built once and kept across dispatcher attempts, which is what makes the truncation escalation reach a retry: the client bumps the SENT message's budget to the model ceiling, and the re-run sends that same message. The binding is re-minted per attempt and prices exactly the conversation the wire sends, input under the resolved tokenizer, output from the declaration, thinking from the spec and depth, so reservation and max_tokens cannot drift.

Since:
0.1 (2026-09-17)
Author:
Andrey Santrosyan
  • Constructor Details

    • AbstractModelDependentTool

      protected AbstractModelDependentTool(Identifiable parent)
      A tool that learns its grade later, from its input or from the thinker that offers it.
    • AbstractModelDependentTool

      protected AbstractModelDependentTool(Identifiable parent, Grade grade)
      A tool whose grade is its own decision.
    • AbstractModelDependentTool

      protected AbstractModelDependentTool(Identifiable parent, String idPrefix, Grade grade)
      With a job id prefix of its own.
  • Method Details

    • getGrade

      public Grade getGrade()
      Description copied from interface: ModelDependent
      The grade the seat declares; Grade.CEILING for the strongest the deployment serves.
      Specified by:
      getGrade in interface ModelDependent
    • setGrade

      public void setGrade(Grade grade)
      Description copied from interface: ModelDependent
      Raises or lowers the declared grade for a run; a thinker refuses null.
      Specified by:
      setGrade in interface ModelDependent
    • pinModel

      public void pinModel(ModelSpec model)
      Description copied from interface: ModelDependent
      Runs the seat on this exact entry instead of resolving its grade. Null unpins.
      Specified by:
      pinModel in interface ModelDependent
    • pinnedModel

      public ModelSpec pinnedModel()
      Description copied from interface: ModelDependent
      The entry the seat is pinned to, or null when it resolves its grade.
      Specified by:
      pinnedModel in interface ModelDependent
    • wireConversation

      protected <T> ModelBinding wireConversation(JobRequirements req, Depth depth, OutputDeclaration output, Class<T> outputType, String additionalInstructions)
      Builds this tool's conversation once and wires a fresh binding onto it for this attempt, from the pinned entry or the declared grade. Called from getRequirements, which the dispatcher runs at submit and again per attempt.
      Parameters:
      output - how much answer the call books: a rung sized to the output POJO, or a count where the tool's own instruction fixes the answer precisely
    • wireConversation

      protected ModelBinding wireConversation(JobRequirements req, Depth depth, Supplier<ConversationContext> builder)
      Wires a conversation the tool builds itself - one carrying images or files, or any shape the rendered input prompt cannot express - built once through the supplier on the first call and given a fresh binding per attempt, exactly as the prompt form is. The tool then converses through converse(JobResources), so its answer is corrected the same way; a tool that sends its own conversation on the client instead loses that.
    • request

      protected <T> LLMRequest<T> request()
      The request for the conversation wireConversation(JobRequirements, Depth, OutputDeclaration, Class, String) built; execute sends it on the client resolved for its binding.
    • converse

      protected <T> T converse(JobResources resources) throws LLMReadableCheckedException
      Sends the wired conversation on the client resolved for its binding and returns the typed answer, correcting the model the way LLMCall does: an answer that does not parse, or parses without its required fields, goes back to the model as a correction turn and the dispatcher re-runs this same instance, up to ResponseCorrection.MAX_CORRECTIONS times. The retry signals this throws are the dispatcher's; a tool that wraps them in a catch loses the correction, which is why LLMReadableCheckedException.unwrap(Throwable) lets them through.
      Throws:
      LLMReadableCheckedException
    • client

      protected LLMClient client(JobResources resources)
      The client for the wired conversation's resolved model. A test overrides it to answer without a transport.
    • buildInputPrompt

      protected String buildInputPrompt(String additionalInstructions)
      Builds the prompt text that wireConversation(JobRequirements, Depth, OutputDeclaration, Class, String) sends to the LLM: the input serialized as context, then the tool's instructions.