Package com.veeva.vault.sdk.api.ai


package com.veeva.vault.sdk.api.ai
This package provides interfaces and classes for AI operations.

Use Case: Defining a Context Type Runtime Handler

The AiContextTypeRuntimeHandler entrypoint can be used to define a handler for generating context sent to an LLM as part of an agent action execution

1. Define the context type runtime handler class:
 
     @ExecuteAs(ExecuteAsUser.REQUEST_OWNER)
     @AiContextTypeRuntimeHandlerInfo(scope = AiScope.DOCUMENT)
     public class MyContextTypeRuntimeHandler implements AiContextTypeRuntimeHandler {
         @Override
         public AiContextTypeResolveResponse onResolve(AiContextTypeResolveContext context) {
             AiDocumentScopeSource documentScopeSource = context.getScopeSource(AiScopeType.DOCUMENT);
             DocumentVersion documentVersion = documentScopeSource.getDocumentVersion();
             String documentName = documentVersion.getValue("name__v", ValueType.STRING);

             AiContextTypeOutputItem contextOutput = context.newOutputItemBuilder()
                     .withText("The current document name is [" + documentName + "]")
                     .build();

             return context.newSuccessResponseBuilder()
                     .appendOutputItem(contextOutput)
                     .build();
         }
     }
 
 

2. Create the Aicontexttype record
 
      RECREATE Aicontexttype my_context_type__c (
          label('My Context Type'),
          admin_configurable(true),
          runtime_code('Aicontexttyperuntimecode.com.veeva.vault.custom.context.MyContextTypeRuntimeHandler')
      );
 
 

Use Case: Defining a Tool Type Runtime Handler

The AiToolTypeRuntimeHandler entrypoint can be used to define a handler for tool spec generation and tool execution when invoked by an LLM

1. Define the tool type runtime handler class:
 
     @ExecuteAs(ExecuteAsUser.REQUEST_OWNER)
     @AiToolTypeRuntimeHandlerInfo(dynamicToolSpec = false)
     public class MyToolTypeRuntimeHandler implements AiToolTypeRuntimeHandler {
         @Override
         public AiToolTypeExecutionResponse onExecute(AiToolTypeExecuteContext context) {
             JsonService jsonService = ServiceLocator.locate(JsonService.class);
             RecordService recordService = ServiceLocator.locate(RecordService.class);

             // Create a new record and return the created ID
             Record newRecord = recordService.newRecord("tool_invocations__c");
             String nameInput = context.getInput().getValue("name", JsonValueType.STRING);
             newRecord.setValue("name__v", nameInput);

             JsonObjectBuilder toolOutput = jsonService.newJsonObjectBuilder();

             RecordBatchSaveRequest saveRequest = recordService.newRecordBatchSaveRequestBuilder()
                     .withRecords(VaultCollections.asList(newRecord))
                     .build();
             recordService.batchSaveRecords(saveRequest)
                     .onSuccesses(successes -> {
                         toolOutput.setValue("recordId", successes.get(0).getRecordId());
                     })
                     .rollbackOnErrors()
                     .execute();

             return context.newSuccessBuilder(AiToolTypeExecutionResponse.JsonResultBuilder.class)
                     .withJson(toolOutput.build())
                     .build();
         }
     }
 
 

2. Create the Aitooltype record
 
      RECREATE Aitooltype my_tool_type__c (
          label('My Tool Type'),
          admin_configurable(true),
          description ('Sample tool to create a Tool Invocations record'),
          runtime_code('Aitooltyperuntimecode.com.veeva.vault.custom.context.MyToolTypeRuntimeHandler')
      );
 
 

Use Case: Defining a Dynamic Tool Type Runtime Handler

The AiToolTypeRuntimeHandler entrypoint can be used to define a handler for tool spec generation and tool execution when invoked by an LLM

1. Define the tool type runtime handler class:
 
 @ExecuteAs(ExecuteAsUser.REQUEST_OWNER)
 @AiToolTypeRuntimeHandlerInfo(dynamicToolSpec = true)
 public class MyDynamicToolTypeHandler implements AiToolTypeRuntimeHandler {

     @Override
     public AiToolTypeExecutionResponse onExecute(AiToolTypeExecuteContext context) {
         RecordService recordService = ServiceLocator.locate(RecordService.class);

         JsonObject inputs = context.getInput();
         Map<String, JsonProperty> properties = inputs.getProperties();

         Record newCountry = recordService.newRecord("country__v");

         properties.forEach((fieldName, property) -> {
             newCountry.setValue(fieldName, inputs.getValue(fieldName, JsonValueType.STRING));
         });

         RecordBatchSaveRequest saveRequest = recordService.newRecordBatchSaveRequestBuilder()
                 .withRecords(VaultCollections.asList(newCountry))
                 .build();

         recordService.batchSaveRecords(saveRequest)
                 .onErrors(batchOperationErrors -> {
                     throw new RollbackException("MYDYNAMICTOOLTYPE_ERROR", batchOperationErrors.get(0).getError().getMessage());
                 })
                 .execute();

         return context.newSuccessBuilder(AiToolTypeExecutionResponse.TextResultBuilder.class)
                 .withText("MyDynamicToolTypeHandler executed successfully")
                 .build();
     }

     @Override
     public AiToolTypeGenerateInputResponse onGenerateInput(AiToolTypeGenerateInputContext context) {
         ObjectMetadataService objectMetadataService = ServiceLocator.locate(ObjectMetadataService.class);

         ObjectFieldMetadataCollectionRequest request = objectMetadataService.newObjectFieldMetadataCollectionRequestBuilder()
                 .withObjectName("country__v")
                 .build();

         ObjectFieldMetadataCollectionResponse personMetadata = objectMetadataService.getObjectFieldMetadataCollection(request);

         List<ObjectFieldMetadata> fields = personMetadata.getFields();

         LlmToolInputObject.Builder inputBuilder = context.newObjectLlmToolItemBuilder();

         for (ObjectFieldMetadata field : fields) {
             if (!(field.getValueType() == ValueType.STRING)) {
                 continue;
             }

             LlmToolInputItem item = context.newSimpleTypeLlmToolItemBuilder()
                     .withType(LlmToolInputItemType.STRING)
                     .build();
             inputBuilder.addProperty(field.getName(), item);
         }

         return context.newSuccessBuilder()
                 .withInput(inputBuilder.build())
                 .build();
     }
 }
 
 
2. Create the Aitooltype record
 
      RECREATE Aitooltype my_dynamic_tool_type__c (
          label('My Dynamic Tool Type'),
          admin_configurable(true),
          description ('Sample tool to create a country__v record'),
          runtime_code('Aitooltyperuntimecode.com.veeva.vault.custom.context.MyDynamicToolTypeHandler')
      );